Xpath 1.0: ancestor-or-self :: NameTest / NameTest [предикат] не работает должным образом - PullRequest
0 голосов
/ 03 мая 2018

Я имею дело со словарем XML, который имеет «значения по умолчанию»: то есть, если узел не имеет определенного подузла, я хотел бы найти ближайший вмещающий узел, который имеет этот подузел, и использовать его строковое значение как значение подузла исходного узла.

Например, если у меня есть дерево

Super_node
    sub_node: XXX
    ...
        context_node
            /* does not have a child with name sub_node */

и нет промежуточных узлов между Super_node и context_node, есть дочерний элемент sub_node, я хочу выражение, которое оценивается как XXX.

Я думал, что следующий запрос должен работать, но я всегда получаю список узлов:

string(ancestor-or-self::*/sub_node[1]/text())

Я думаю, что ancestor-or-self::* возвращает в обратном порядке документов список context_node, parent_of_context_node, ..., Super_node. Я применяю к этому тест sub_node и получаю список sub_node в этом списке, опять же, надеюсь, в обратном порядке документов.

Затем я применяю предикат [1], который должен возвращать первый элемент этого списка. Однако этот предикат кажется неэффективным: в моей реализации (которая, я думаю, основана на libxml2) я все еще получаю список.

Что работает, я нашел после того, как немного поковырялся в Stack Exchange, это

string((ancestor-or-self::*/sub_node)[last()]/text())

Почему предикат [1] выше не эффективен?

1 Ответ

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

Выражение

ancestor-or-self::*/sub_node[1]

означает

ancestor-or-self::*/(child::sub_node[1])

, который выбирает первый sub_node дочерний элемент каждого элемента-предка.

Я подозреваю, что вы думали о

(ancestor-or-self::*/sub_node)[1]

, который выбирает все sub_node дочерние элементы всех элементов-предков, сортирует их в порядке документов и затем возвращает первый узел в этом списке.

Предикаты типа [1] связываются сильнее, чем "/".

...