Simeon
Simeon

Reputation: 7792

Select an XML element regardless of level with XPATH

I have this:

<a>
  <b>
    <t>text</t>
  </b>
</a>
<a>
  <t>text</t>
</a>

So I want to select the text regardless of where is it. (note that it can be anywhere not just 1/2 levels down, it can have no parents for instance)

Is this possible?

Upvotes: 23

Views: 43564

Answers (4)

cbaldan
cbaldan

Reputation: 553

W3Schools has really good free courses regarding everything that is HTML related. I highly recommend reading it and making the examples. https://www.w3schools.com/xml/xpath_intro.asp

HINT: you can use your browser's console to evalute expressions. It's under Developer Tools - F12 key for Chorme and Firefox:

$x('<your expressions>');

So, as everyone said, you can use the // syntax to find an element anywhere in the page. e.g. //a will return you all a elements within the page.

Most likely you will want a specific one, so, that's where you use the predicates. They are contained between brackets. Using this very page as example, here is a xquery:

//a[text()="Simeon"]

This xpath will return all a elements that have Simeon as it's text. In many situations you might need to improve you xpath to include more identifiers, be more specific.

//a[text()="Simeon" AND @href="/users/274344/simeon"]

So, you can use pretty much any HTML attribute, or even CSS to identify a specific node you want.

But now, let´s take it up a notch. Let´s say you want to get the a element that is below user's mkimd answer from Jan 27. If you look at this page structure, you have to get you a and dive back a few levels, untill you are able to reach the span that holds the posting date.

//a[text()="mkimd" AND ../../div[@class="user-action-time"]/span[contains(.,"Jan")]]

There are many ways of doing these queries,this last example I gave can be achieved with different xqueries.

I find that xqueries are very similar to navigation in directories in console, like Linux BASH - relative and absolute paths, and the identifiers are like SQL WHERE clauses.

If you research, there are many functions available in XPATH syntax, such as

  • lower-case()
  • upper-case()
  • concat()
  • ends-with()
  • operators ( +,-,*,div,!=,<,<=,>, ...)

I highly advise you to use some tool like Firefox Firefug FirePath addon to practice xquery and check if you are getting the element you want - it highlights the elements found.

====================

EDIT - May-8th-15

In case you are using Xpath in Selenium automation, know that it will not help you select CSS pseudo elements.

Upvotes: 0

user357812
user357812

Reputation:

You are looking for the descendant axis:

the descendant axis contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus the descendant axis never contains attribute or namespace nodes

In your case: /descendant:t

Of course, as others have answered, there is an abbreviated syntax for this:

// is short for /descendant-or-self::node()/. For example, //para is short for /descendant-or-self::node()/child::para and so will select any para element in the document (even a para element that is a document element will be selected by //para since the document element node is a child of the root node)

Upvotes: 33

Chris Cameron-Mills
Chris Cameron-Mills

Reputation: 4657

You can use // to select all nodes from the current node. So //text() would select all text nodes.

If you wanted all t elements you would do //t. If you wanted to do do all t elements from a certain point you might then do /x/y//t.

Upvotes: 29

mkraemerx
mkraemerx

Reputation: 1833

just //t if you want all <t> tags

Upvotes: 10

Related Questions