Текущий выбранный ответ неверен .
На самом деле //someExpression[2]
может выбрать много узлов.
Например, если у нас есть следующий XML-документ :
<lib:library xmlns:lib="UNDEFINED!!!">
<topic name="XML">
<lib:book> XML </lib:book>
</topic>
<topic name="XPath">
<lib:book> XPath </lib:book>
</topic>
<topic name="XSLT">
<lib:book> XSLT1 </lib:book>
<lib:book> XSLT2 </lib:book>
</topic>
<topic name="Imperative PLs">
<lib:book> Java </lib:book>
<lib:book> C++ </lib:book>
</topic>
</lib:library>
При выражении :
//*[local-name() = "book"][2]
сравнивается с указанным выше документом, выбраны два узла (и ни один из них не является вторым узлом в документе с требуемыми свойствами):
<lib:book xmlns:lib="UNDEFINED!!!"> XSLT2 </lib:book>
<lib:book xmlns:lib="UNDEFINED!!!"> C++ </lib:book>
Решение : Один из способов выбора N
-го (скажем, 2-го) узла (скажем, lib:book
) во всем документе:
(//*[local-name() = "book"])[2]
Когда это выражение оценивается в приведенном выше документе, выбирается правильный единственный узел:
<lib:book xmlns:lib="UNDEFINED!!!"> XPath </lib:book>
Пояснение : Как определено в Рекомендациях W3C XPath :
//
- это сокращение от /descendant-or-self::node()/
Таким образом:
//someName[2]
является сокращением для:
/descendant-or-self::node()/someName[2]
, и это выбирает любой элемент в документе с именем someName
, который является вторым someName
дочерним элементом его родителя.
Другими словами, оператор []
связывается сильнее (имеет более высокий приоритет), чем псевдо-оператор //
. Вот почему нам нужны скобки, чтобы переопределить приоритет оператора по умолчанию.