XPath: выберите первый элемент с определенным атрибутом - PullRequest
273 голосов
/ 17 июня 2009

XPath bookstore/book[1] выбирает первый книжный узел под bookstore.

Как выбрать первый узел, который соответствует более сложному условию, например, первый узел, который соответствует /bookstore/book[@location='US']

Ответы [ 9 ]

395 голосов
/ 17 июня 2009

использование (/bookstore/book[@location='US'])[1]

Сначала будут получены элементы книги с атрибутом местоположения, равным «США». Затем он выберет первый узел из этого набора. Обратите внимание на использование скобок, которые требуются в некоторых реализациях.

(обратите внимание, что это не то же самое, что /bookstore/book[1][@location='US'], если только первый элемент не имеет этот атрибут местоположения )

163 голосов
/ 23 февраля 2012

/bookstore/book[@location='US'][1] работает только с простой структурой.

Добавьте немного больше структуры и все сломается.

С

<bookstore>
 <category>
  <book location="US">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
</bookstore> 

/bookstore/category/book[@location='US'][1] выход

<book location="US">A1</book>
<book location="US">B2</book>

не "первый узел, который соответствует более сложному условию". /bookstore/category/book[@location='US'][2] ничего не возвращает.

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

(/bookstore/category/book[@location='US'])[1] дает

<book location="US">A1</book>

и (/bookstore/category/book[@location='US'])[2] работают как положено.

42 голосов
/ 17 июня 2009

Как объяснение ответа Джонатана Фингланда:

  • несколько условий в одном и том же предикате ([position()=1 and @location='US']) должны быть истинными в целом
  • множественные условия в последовательных предикатах ([position()=1][@location='US']) должны быть истинными одно за другим
  • это означает, что [position()=1][@location='US']! = [@location='US'][position()=1]
    в то время как [position()=1 and @location='US'] == [@location='US' and position()=1]
  • подсказка: одинокий [position()=1] может быть сокращен до [1]

Вы можете создавать сложные выражения в предикатах с помощью логических операторов "and" и "or", а также с логическими функциями XPath not(), true() и false(). Кроме того, вы можете заключить подвыражения в скобки.

12 голосов
/ 13 мая 2013

Самый простой способ найти первый англоязычный узел книги (во всем документе), принимая во внимание более сложный структурированный XML-файл, такой как:

<bookstore>
 <category>
  <book location="US">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
</bookstore> 

- это выражение xpath:

/descendant::book[@location='US'][1]

8 голосов
/ 18 марта 2016
    <bookstore>
     <book location="US">A1</book>
     <category>
      <book location="US">B1</book>
      <book location="FIN">B2</book>
     </category>
     <section>
      <book location="FIN">C1</book>
      <book location="US">C2</book>
     </section>
    </bookstore> 

Итак, учитывая вышеизложенное; Вы можете выбрать первую книгу с помощью

(//book[@location='US'])[1]

И он найдет первый, где есть США. [A1]

//book[@location='US']

Возвращает набор узлов со всеми книгами с местоположением US. [А1, В1, С2]

(//category/book[@location='US'])[1]

Возвращает первое местоположение книги США, которое существует в категории в любом месте документа. [B1]

(/bookstore//book[@location='US'])[1]

вернет первую книгу с местоположением US, которое существует в любом месте под книжным магазином корневого элемента; делая часть книжного магазина избыточной. [A1]

Прямой ответ:

/bookstore/book[@location='US'][1]

Вернет вам первый узел для элемента книги с местоположением US, находящимся в книжном магазине [A1]

Кстати, если хотите, в этом примере найдите первую американскую книгу, которая не была прямым потомком книжного магазина:

(/bookstore/*//book[@location='US'])[1]
2 голосов
/ 17 августа 2017

Используйте индекс для получения нужного узла, если xpath сложный или более одного узла присутствует с одинаковым xpath.

ex: (// bookstore [@location = 'US']) [index]

Вы можете указать номер нужного вам узла.

0 голосов
/ 27 июня 2019

если в данном xml предусмотрено пространство имен, лучше использовать это.

(/*[local-name() ='bookstore']/*[local-name()='book'][@location='US'])[1]
0 голосов
/ 15 июля 2017

С помощью онлайн xpath tester Я пишу этот ответ ...
Для этого:

<table id="t2"><tbody>
<tr><td>123</td><td>other</td></tr>
<tr><td>foo</td><td>columns</td></tr>
<tr><td>bar</td><td>are</td></tr>
<tr><td>xyz</td><td>ignored</td></tr>
</tbody></table>

следующий xpath:

id("t2") / tbody / tr / td[1]

выходы:

123
foo
bar
xyz

Поскольку 1 означает выбрать все элементы td , которые являются первыми дочерними элементами своего собственного прямого родителя.
Но следующий xpath:

(id("t2") / tbody / tr / td)[1]
* * 1 022 Выходы: * +1023 *
123
0 голосов
/ 17 марта 2017

например

<input b="demo">

И

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