Java 使用;“祖先”;在xpath中使用相对路径

Java 使用;“祖先”;在xpath中使用相对路径,java,xml,xpath,relative-path,ancestor,Java,Xml,Xpath,Relative Path,Ancestor,我有一个类似于 <Employees> <Employee> <GenericData> <Data> <ID>1</ID> <Name>ABC</Name> </Data> </GenericData> <

我有一个类似于

<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>
需要在祖先之后使用相对路径的解决方案,例如:

//Data/Name[text()=\"ABC\"]/ancestor::Employee/*/DeptName/text()
使用*删除部门数据/子部门,即使用相对路径


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

您需要在最低的节点上设置谓词,该节点是名称和id的共享祖先,并从该节点访问目标数据:

/Employees/Employee[./GenericData/Data/Name/text() = "ABC"]/DepartmentData/SubDepartment/DeptID/text()
这将查找员工,仅保留具有相关名称的员工,然后提取他们的部门ID


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

如果
部门名称对
员工来说是唯一的,您可以使用
/

//Data/Name[text()="ABC"]/ancestor::Employee//DeptName/text()
或者与@Aaron的方法相同,我认为这更直观。此外,如果您可以使用XPath 2.0,您可以将
Employee
或其他staff存储在一个变量中以提高可读性,正如您所说,您的XML非常复杂:

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