XSLT: вернуть значение определенного потомка, если оно присутствует у одного из родителей в дереве предков. - PullRequest
0 голосов
/ 20 мая 2018

У меня есть XML со структурой, аналогичной приведенной ниже.

<root>
    <randomElement>..</randomElement>
    <EFFECT>..</EFFECT>
    <parent2>
        <randomElement>..</randomElement>
        <EFFECT>..</EFFECT>
        <parent>
            <randomElement>..</randomElement>
            <EFFECT>..</EFFECT>
            <randomElement>..</randomElement>
            <ITEM>..</ITEM>
        </parent>
    </parent2>
</root>

Примечание: в местах, где он указан, может быть любое количество <randomElement> с.

Итак, сейчас мой указатель находится на теге <ITEM>.Мне нужно вернуть значение внутри тега <EFFECT>, но здесь есть подвох.

Если он присутствует , я должен вернуть значение тега <EFFECT>, которое находится внутри тега <parent>.Если его там нет, я должен вернуть значение тега <EFFECT>, которое находится внутри тега <parent2>.Опять же, если его там тоже нет, мне нужно наконец вернуть значение тега <EFFECT>, которое находится внутри <root>.<EFFECT> внутри <root> всегда будет присутствовать, и для элемента <ITEM> может быть любое количество родителей.

Извините, если это сбивает с толку.

1 Ответ

0 голосов
/ 20 мая 2018

Чтобы перейти к любому <ITEM>, этого достаточно.

//ITEM

Теперь <EFFECT> - это брат <ITEM>, то есть он находится на том же уровне.Другой способ думать о братьях и сестрах - это то, что они являются потомками одного и того же родителя.

Фактически, все рассматриваемые элементы <EFFECT> являются потомками какого-то предка <ITEM>.Это означает, что мы можем двигаться вверх вдоль оси ancestor:: и захватить все элементы-предки за один шаг:

//ITEM/ancestor::*

Это даст нам <parent>, <parent2> и <root> в этом порядке.

И из тех нам нужно сделать только один шаг вниз, чтобы захватить все <EFFECT> элементов:

//ITEM/ancestor::*/EFFECT

Это даст нам три EFFECT элементов, на этот раз снова в порядке документа (только ось типа ancestor:: работает наизнанку).

Нас интересует последний из них, потому что он будет наиболее близок к <ITEM>, с которого мы начали.Функция last() поможет здесь:

(//ITEM/ancestor::*/EFFECT)[last()]

Круглые скобки вокруг пути необходимы, потому что в противном случае условие ([last()]) проверяется на каждом <EFFECT> в отдельности, и каждое из них являетсяпоследний в своем роде для своего родителя, давая нам три матча.Скобки делают так, что сначала создается набор узлов из трех <EFFECT> элементов, а , а затем - последний, что дает нам только одно совпадение.

Когда вы уже в данный момент находитесьв элементе <ITEM> относительная версия пути выбирает последний эффект для этого конкретного элемента:

(ancestor::*/EFFECT)[last()]
...