What's the difference between //node and /descendant::node in xpath?

Viewed 54375

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

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.

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
Related