использование «предка» в xpath с относительным путем - PullRequest
0 голосов
/ 04 февраля 2020

У меня xml похож на

<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()

Удаление DepartmentData / SubDepartment с помощью *, то есть с использованием относительного пути.

Примечание: Мой фактический xml слишком сложен, и написание целого пути невозможно. Любая помощь высоко ценится.

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

Вы захотите установить предикат на самом нижнем узле, который является общим предком как имени, так и идентификатора, и получить доступ к целевым данным оттуда:

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

Это ищет сотрудников, сохраняйте только те (тот) с соответствующим Именем, затем извлекают их (его) DeptID.

Это не требует полного пути, например, вы можете использовать //Employee, если хотите. Тем не менее, использование // может оказать значительное влияние на производительность, и его редко необходимо использовать.

0 голосов
/ 04 февраля 2020

Если 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()
...