tags:

views:

475

answers:

3

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']
+9  A: 

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.

Jonathan Fingland
I should have scoured the TR before asking. For others http://www.w3.org/TR/xpath#path-abbrev is the relevant section. It would appear though that // is short for descendant-or-self so not exactly the same. Also, the reason I've stayed away from using // is that //node[1] is not the same as /descendant::node[1]
Dave Hunt
I've expanded on that point above. // is not descendant-or-self, it is descendant-or-self/child.... which looks an awful lot like descendant to me.
Jonathan Fingland
Agreed. Well noted. :)
Dave Hunt
+2  A: 

Other than terseness, I'm not aware of any difference.

Allain Lalonde
+1  A: 

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.

Motty