2015-11-25 4 views
4

Я не могу понять различия между использованием //element и /descendant::element при выборе нескольких дочерних элементов базового элемента в XPath.Различия между // и/потомок в XPath, выбирая несколько дочерних объектов

Учитывая этот фрагмент кода HTML

<html> 
<body> 
<div class="popupContent"> 
    <table> 
    <tr class="aclass"><td> Hello </td> <td> <input type="text" value="FIRST" /> </td></tr> 
    <tr class="aclass"><td> Goodbye </td> <td> <input type="text" value="SECOND" /> </td></tr> 
    </table> 
</div> 
</body> 
</html> 

нужно выбрать каждый input на основе ее позиционирования в таблице. //div[@class='popupContent']//input[1] это выбирает первый входной //div[@class='popupContent']//input[2] это дает ошибку //div[@class='popupContent']/descendant::input[1] это снова выбирает первый вход //div[@class='popupContent']/descendant::input[2] это выбрать второй вход

Использование /descendant::input делает то, что мне нужно: захватить все входы и позвольте мне выбрать положение.
Каким образом // отличается? Почему он возвращает только первый элемент, а не тот, который после?

Я знаю this other question, но ответ в основном говорит, что они являются псевдонимами и указывают на документацию, которую я не могу понять и не имеет конкретного примера.

+0

первое выражение '// div [@ class = 'popupContent'] // input [1]' возвращает оба входа. – splash58

ответ

1

Единственное различие между //X и /descendant::X, когда Х содержит позиционный предикат, например //x[1] против /descendant::x[1]. В этой ситуации //x[1] выбирает каждый элемент x, который является первым x дочерним элементом его родительского элемента, тогда как /descendant::x[1] выбирает первый потомок x в целом. Вы можете это исправить, вспомнив, что //x[1] не подходит для /descendant-or-self::node()/child::x[1]

10

По XPath 1.0, §2.5 Abbreviated Syntax:

// коротка для /descendant-or-self::node()/

Так div[@class='popupContent']//input[1] (такой же, как div[@class='popupContent']/descendant-or-self::node()/child::input[1]) будет:

  1. идут ко всем потомкам (дети, дети детей и т. д.) div с этим классом popupContent,
  2. затем искать <input> детей
  3. и, наконец, выбрать первого ребенка своего родителя ([1] предиката)

div[@class='popupContent']//input[2] очень похожи, за исключением последнего, что является выбор 2-го ребенка. И ни один из <input> s не является вторым ребенком их родителя.

div[@class='popupContent']/descendant::input[2] с другой стороны будет:

  1. перейти ко всем потомкам div с с этим классом,
  2. выбирая только <input> элементы и построить множество узлов из них
  3. , наконец, выберите второй элемент в этом наборе узлов, в заказе на поставку

Вы можете использовать d о предикатах и ​​осях в §2.4 Predicates. Соответствующие образцы:

(...) предки, предки или предшественники, предшествующие и находящиеся на родном языке, являются обратными осями; все остальные оси - передние оси.

[Таким образом, descendant является передней осью.]

близости положения члена а определяются набор узлов по отношению к оси, чтобы быть положения узла набор узлов, упорядоченный в порядке документа, если ось является передней осью (...). Первая позиция равна 1.

Предикат фильтрует набор узлов относительно оси для создания нового набора узлов. Для каждого узла в наборе узлов, который должен быть отфильтрован, PredicateExpr оценивается с этим узлом в качестве контекстного узла с количеством узлов в наборе узлов в качестве размера контекста и с позицией близости узла в набор узлов относительно оси в качестве контекстной позиции;

Смежные вопросы