Выберите первый результат в XPath - PullRequest
9 голосов
/ 21 мая 2009

Я смотрел на этот вопрос: Выберите первый экземпляр только с XPath?

Но если у меня есть такой набор узлов:


<container value="">
  <data id="1"></data>
  <data id="2">test</data>
  <container>
    <data id="1">test</data>
    <data id="3">test</data>
  </container>
</container>

Теперь мой сценарий состоит в том, что этот набор узлов находится глубоко внутри документа, и у меня есть указатель на внутренний контейнер. Поэтому я должен добавить к моему XPath префикс «/ container / container» (путь на самом деле длиннее, но для этого примера это должно подойти).

EDIT: То, что я хочу, - это узел данных с идентификатором 1, который должен исходить от самого нижнего узла или ближайшего предка. Итак, если я не могу найти его в «текущем» (/ container / container), я должен посмотреть на предков и найти ближайшего (или, в конце концов, ничего не найти). Я пробовал это:

/ контейнер / контейнер / предок или-я :: контейнер / данные [@ ID = "1"]

Что возвращает набор результатов с двумя узлами. Я думал, что смогу использовать last (), чтобы получить самый глубокий, поэтому я добавил это в конце, но безрезультатно.

Ответы [ 5 ]

11 голосов
/ 21 мая 2009

Убедитесь, что last() правильно определена. Попробуйте:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()]

Аналогично:

//container[last()]

и

(//container)[last()]

это не одно и то же. Первый вернет последний контейнерный узел на каждом уровне иерархии - несколько совпадений - а второй вернет последний найденный контейнерный узел - одно совпадение.

6 голосов
/ 21 мая 2009

Как вы пытались прикрепить last ()? Я думаю, что это должно работать:

/container/container/ancestor-or-self::container/data[@id="1"][last()]

EDIT:

Правильно, конечно, я забыл скобки:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()]

Что делает это так же, как один из других ответов; однако, как указывает оригинальный плакат, это выражение не выполняется:

<container value="">
  <container>
    <data id="1">a3</data>
    <data id="3">a4</data>
  </container>
  <data id="1">a1</data>
  <data id="2">a2</data>
</container>

В соответствии с духом stackoverflow, однако, я могу объединить свой ответ с одним из других ответов и получить что-то, что работает во всех случаях:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"]

Кстати, если в одном контейнере есть несколько дочерних элементов @ id-is-1 , все они будут возвращены. Чтобы вернуть только первый такой элемент:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"][1]
1 голос
/ 21 мая 2009

Я не на 100% понимаю, о чем вы спрашиваете, но если я правильно прочитал, может, вы просто захотите:

/container/container/ancestor-or-self::container[1]/data[@id='1']

обратите внимание на «[1]»

Редактировать: подумал об этом немного больше, и ниже работает для меня во всех случаях до сих пор ищет @ id = $ N

/container/container/ancestor-or-self::container[data[@id=$N]][1]/data[@id=$N]

Довольно экстремальный xpathing прямо там. По сути, происходит то, что набор узлов из ancestor-or-self возвращает самый низкий порядок в позиции 1 - это тот, который вам нужен - но вам нужно наложить второе условие, чтобы этот узел также имел интересующий вас узел данных как только вы выполнили эти условия, у вас есть правильный узел, теперь вы просто хотите туннелировать дальше к фактическим данным.

99% времени xpath становится легче, если вы разберете его и будете думать об этом как об алгоритме:)

0 голосов
/ 20 декабря 2013

попробовать [Положение () = 1] * * тысяча одна

ех.

/ контейнер / контейнер / предком или-я :: контейнер / данные [положение () = 1]

0 голосов
/ 21 мая 2009

вместо

@id="1"

Вы пробовали:

position() == 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...