Chapter 5 - XPaths



Transcripted Summary

XPaths are the strongest locator type. XPaths Syntax can uniquely identify any element on a page. It can be used for both HTML and XML documents. However, XPath is also the most complicated locator type.

Let's learn about XPaths using examples for the DuckDuckGo search results page. The easiest way to learn XPath is by example.

Let's say we want to run an XPath starting at the root of the page.

We start by writing a single slash and then we just simply write the chain of elements going down to where we want, html being the root element and then maybe the body.

Locate by Path from Root

/html/body
1

As we can see, the entire body is highlighted here. However, it's not very convenient to write every single XPath from the root element. Instead, we can use a double slash to search for an element by tag anywhere in the page, such as an input tag.

Locate by Tag Anywhere

//input
1

Here we can see there are five different input tags.

We can also mix the single slash and the double slash for direct children.

Let's say I wanted to find links that are in a list. I can start with a double slash and find any unordered list on the page, and then I can use single slashes to denote direct children "ul/li". I could use another single slash to indicate direct children of links on that page.

Locate by Direct Children

//ul/li/a
1

And so here we can see the links from the web images, video and news links at the top.

We can also look for any element on the page with an asterisk.

Locate by Any Element

//*
1

Here we can see there are 520 elements on the page. It may be more useful though to put that in a chain such as I want to find any elements that are children or sub children of developments.

Locate by Any Descendants

//div//
1

XPaths can also select elements based on their attributes.

For example, let's look at these links under the search bar. We can see that they're all list items with this "zcm__item" class. We can write an XPath easily to select these list items based on their class name. What we do is first we start with the list item tag and then we use the square brackets to denote an attribute condition.

Start the attribute name with the at sign (@) and then write the attribute name thereafter, in this case class. If we want to check a value, we can say the attribute equals whatever the value is, "zcm__item".

Locate by Attribute Value Equality

//li[@class='zcm__item']
1

And just like that we can see that this XPaths selects these four links with this class name.

XPaths can also have logical AND and OR operations for those conditional phrases.

For example, let's say that I want to find all of these small icon images on the page that are small in size. I can write an XPath like this, give me the image where the width is less than 20 and the height also is less than 20.

Locate by Attribute Condition AND

//img[@width<20][@height<20]
1

Whenever we stack these conditional freezes on our Xpaths, they act like a logical AND —it means make sure that this particular element meets every single one of these conditions. So, both the width and the height must be less than 20, and I can see that that gives me all those little icons in my search results.

I could also write the logical AND using one set of square brackets, using the AND operator, just like that.

Locate by Attribute Condition AND

//img[@width<20 and @height<20]
1

It's functionally the same as stacking on multiple square bracket phrases.

Now, let's see how to do a logical OR operator and why I might want to do that.

Let's write a selector for the search bar at the top. We know that this input element can be uniquely identified either by its name or by its id. If we wanted to make a very, very robust locator using XPath, we could select that element based on either or of these identifiers — input where the name equals "q" or the id equals "search_form_input".

Locate by Attribute Condition OR

//input[@name='q' or @id='search_form_input']
1

Using this logical OR, this element will need to have either the name being q or the id being "search_form_input".

On this page, both of those will uniquely point at one element.

But let's say in the future someone were to change that name value or were to change this ID value without also updating your test automation. In that case, as long as one of them still works, this locator will still identify that element. There's a safety factor in play.

Another very powerful part of the XPath Syntax is it's set of functions which really help to make better attribute conditions.

For example, let's say that I want to get the snippets from my search results. We can see that the snippets are div elements with two classes, "result__snippet" and "js-result-snippet".

If I were to write a locator checking if the class equals "result__snippet"...

//div[contains(@class = 'result__snippet')]
1

...I'll find that I don't have any results for that. And that's because I don't need to check if the class is equal to a value. I want to check if the class contains a value. For that I need the contains function.

The contains function is basically a sub string operation.

It will check to see if whatever string literal or expression you put here is contained within the text of the expression you pass here. In this case, the value attribute.

Locate by Contains Function

//div[contains(@class, 'result__snippet')]
1

When I use the contains function, I can see that I get 10 results on my page, which is exactly what I want.

Typically, when you use XPaths to find class names, contains is the good function to use. However, I will caution because this does a sub string operation and not a list containing operation.

If I were to look at all divs that contain the word "result" in their class...

//div[contains(@class, 'result')]
1

...you can see that there may be a lot of false positives. This example here for this element contains the word "result" in its "js-serp-results" class, so that may not necessarily be the element I want to check.

Another helpful XPath function is the "starts-with" function.

The starts-with function will check if an attribute or expression begins with a particular word or phrase. So, I could say "div starts-with class being the attribute I want to check if that class starts with the word 'result'."

Locate by Starts with function

//div[starts-with(@class, 'result')]
1

And here are my search results I can see all the divs that start with a class or being "result". Boom, boom, boom, boom. That can be really helpful for things like classes or text or any other attributes.

A third helpful XPath function is the "not" function.

Let's say that I want to find all links that do not contain the class "header". There's plenty of links like that.

Locate by Logical not function

//a[not(contains(@class, 'header'))]
1

You can see in the class for this link there's no word "header" in there.

You can also notice that you can stack functions. So, I could have said not something else, like not starts-with

//a[not(starts-with(@class, 'header'))]
1



Basic Xpath Rules and Examples

Path from root

/html/body

Tag anywhere

//input

Direct Children

//ul/li/a

Descendants

//div/a

Any Element

//*

Any Descendants

//div//*

Attribute Value Equality

//li[@class='zcm__item']

Attribute Condition AND

//img[@width<20][@height<20]

//img[@width<20 and @height<20]

Attribute Condition OR

//input[@name='q' or @id='search_form_input']

Contains Function

//div[contains(@class, 'result')]

//div[contains(@class, 'result__snippet')]

Starts with function

//div[starts-with(@class, 'result')]

Logical not function

//a[not(contains(@class, 'header'))]

There are many, many other XPath functions available. I encourage you to go look them up online and learn about them.




In our next lesson, we'll look at some more advanced XPath features like text, indices and axes.



Resources