XPath: выберите первый элемент с определенным атрибутом

XPath bookstore/book[1] выбирает первую книгу node под bookstore.

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

Ответ 1

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

Сначала вы получите элементы книги с атрибутом location, равным "US". Затем он выберет первый node из этого набора. Обратите внимание на использование круглых скобок, которые требуются для некоторых реализаций.

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

Ответ 2

/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>

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

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

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

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

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

Ответ 3

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

  • несколько условий в одном и том же предикате ([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(). Кроме того, вы можете заключить подвыражения в круглые скобки.

Ответ 4

Самый простой способ найти первую английскую книгу node (во всем документе), принимая во внимание более сложный структурированный 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]

Ответ 5

    <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']

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

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

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

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

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

В прямом ответе:

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

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

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

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

Ответ 6

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

Пример:

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

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

Ответ 7

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

(/*[local-name() ='bookstore']/*[local-name()='book'][@location='US'])[1]

Ответ 8

для ex.

<input b="demo">

и

(input[@b='demo'])[1]

Ответ 9

С помощью онлайн 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]

выходы:

123