What's the difference between //node and /descendant::node in xpath?
Solution 1
see http://www.w3.org/TR/xpath#path-abbrev
// is just an abbreviation for the descendant:: axis
Edit
To quote:
//para is short for /descendant-or-self::node()/child::para
That is, it refers to all para which are a child of the context node or any node descended from the context node. As far as I can tell that translates into any descendant para of the context node.
Solution 2
There's a difference in the context group. //para[1]
is short for
/descendant-or-self::node()/child::para[1]
, which returns every para that is the first child of its parent. /descendant::para[1]
returns only the first para in the entire subtree.
Solution 3
In your case
id('books')//td[@class='title']
and:
id('books')/descendant::td[@class='title']
return the same result.
But in fact, like it was already stated before, id('books')//td[@class='title']
means id('books')/descendant-or-self::node()/td[@class='title']
which is different from id('books')/descendant::td[@class='title']
in concept.
See the following note:
NOTE: The location path //para[1] does not mean the same as the location path /descendant::para[1]. The latter selects the first descendant para element; the former selects all descendant para elements that are the first para children of their parents.
this note was taken from http://www.w3.org/TR/xpath#path-abbrev
Solution 4
Other than terseness, I'm not aware of any difference.
Solution 5
I realize this answer is more of a functional correctness, but in case it helps anyone, I stumbled across a key difference today.
When selecting elements based on some property of a descendant (like attribute). For example:
...
<foo id="ID1">
<bar>
<baz at2="c" />
</bar>
</foo>
<foo2 id="ID2">
<bar>
<baz at2="d" />
</bar>
</foo2>
...
To select the id
attribute of all elements who have a descendant with an attribute at2=c
:
This xpath will select foo and foo2:
//*[//*[@at2="c"]]/@id
while this xpath will only select foo:
//*[descendant::*[@at2="c"]]/@id
Dave Hunt
I'm an automation engineer developing tools and test solutions for Mozilla and an active contributor to the Selenium open source project.
Updated on March 08, 2021Comments
-
Dave Hunt over 3 years
I use a lot of XPath when locating elements in web pages using Selenium, and have moved away from using node1//node2 towards using node1/descendant::node2 more recently. What's the difference between the two methods? Is one more efficient than the other?
Example XML snippet to demonstrate:
<div id="books"> <table> <tr><td class="title">Lord of the Rings</td><td class="author">JRR Tolkein</td></tr> <tr><td class="title">The Hitch-Hikers Guide to the Galaxy</td><td class="author">Douglas Adams</td></tr> </table> </div>
So it'd be:
id('books')//td[@class='title']
or:
id('books')/descendant::td[@class='title']