在具有相对路径的 XPath 中使用"ancestor"



我有一个类似于

<Employees>
<Employee>
<GenericData>
<Data>
<ID>1</ID>
<Name>ABC</Name>
</Data>
</GenericData>
<DepartmentData>
<SubDepartment>
<DeptID>12</DeptID>
<DeptName>IT</DeptName>
</SubDepartment>
</DepartmentData>
</Employee>
<Employee>
<GenericData>
<Data>
<ID>1</ID>
<Name>XYZ</Name>
</Data>
</GenericData>
<DepartmentData>
<SubDepartment>
<DeptID>13</DeptID>
<DeptName>HR</DeptName>
</SubDepartment>
</DepartmentData>
</Employee>
</Employees>

我的问题是根据名称获取 DeptID。我能够使用以下方法获取相同的内容:

//Data/Name[text()="ABC"]/ancestor::Employee/DepartmentData/SubDepartment/DeptName/text()

需要一个解决方案来使用祖先之后的相对路径,如下所示:

//Data/Name[text()="ABC"]/ancestor::Employee/*/DeptName/text()

使用 * 删除部门数据/子部门,即使用相对路径。

注意:我的实际xml太复杂了,编写整个路径是不可行的。任何帮助都非常感谢。

您需要在作为名称和 id 的共同祖先的最低节点上设置谓词,并从那里访问目标数据:

/Employees/Employee[./GenericData/Data/Name/text() = "ABC"]/DepartmentData/SubDepartment/DeptID/text()

这将查找员工,仅保留具有相关名称的员工(一个(,然后提取他们(其(部门ID。

这不需要完整的路径,例如,如果需要,您可以使用//Employee。也就是说,使用//会对性能产生重大影响,并且很少需要使用。

如果DeptName对于Employee是唯一的,你可以只使用//

//Data/Name[text()="ABC"]/ancestor::Employee//DeptName/text()

或者与我认为更直观的@Aaron方法相同。此外,如果你可以使用XPath 2.0,你可以将Employee或其他员工存储在一个变量中以获得更好的可读性,正如你所说,你的XML非常复杂:

let $Employee := /Employees/Employee[GenericData/Data/Name/text() = "ABC"]
return
$Employee//DeptName/text()

最新更新