Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences between // and /descendant in XPath selecting multiple children

I can't clearly understand the differences between using //element and /descendant::element when selecting multiple children of a base element in XPath.

Given this HTML snippet

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

I need to select each input based on its positioning in the table. //div[@class='popupContent']//input[1] this selects the first input //div[@class='popupContent']//input[2] this gives error //div[@class='popupContent']/descendant::input[1] this again selects the first input //div[@class='popupContent']/descendant::input[2] this select the second input

Using /descendant::input does what I need: grab all inputs and let me select by position.
How does // differ? Why does it return only the first element and not the ones after?

I'm aware of this other question but the answer basically says they're aliases and point to the documentation, which I cannot understand and lacks a concrete example. Difference with that question is that my need is to select multiple children elements, and // doesn't allow it.

like image 413
Alessandro Da Rugna Avatar asked Nov 25 '15 13:11

Alessandro Da Rugna


People also ask

What is the difference between child and descendant in XPath?

child:: are your immediate children. descendant:: are your children, and their children, recursively.

What does descendant mean in XPath?

The descendant axis indicates all of the children of the context node, and all of their children, and so forth. Attribute and namespace nodes are not included - the parent of an attribute node is an element node, but attribute nodes are not the children of their parents.

What is difference between ancestor and parent in XPath?

The difference between parent:: and ancestor:: axis is conveyed by their names: A parent is the immediately direct ancestor. So, yes /a/b/c/d/ancestor::*[1] would be the same as /a/b/c/d/parent::* .

What is the difference between following and following sibling XPath?

The major difference between the following and following siblings is that the following sibling takes all the sibling nodes after the context but will also share the same parent.


1 Answers

The only difference between //X and /descendant::X is when X contains a positional predicate, for example //x[1] vs /descendant::x[1]. In this situation //x[1] selects every x element that is the first x child of its parent element, whereas /descendant::x[1] selects the first descendant x overall. You can work this out by remembering that //x[1] is short for /descendant-or-self::node()/child::x[1]

like image 101
Michael Kay Avatar answered Mar 05 '23 12:03

Michael Kay