In this post, we are going to discuss the XPath and different types and the different expressions which are used to find any elements like complex and dynamic elements in a DOM or a web page.
Every selenium automation test engineer should be comfortable in locating the elements of a web page because of it, the very basic thing in automation. If you are not able to locate the elements in the DOM then, if you write the script, the script will not work. In our previous post, we discuss how we can find the elements by using different locators like ID, Name, TagName, ClassName, LinkText, and Partial Link text. But still, there are two other locating strategies available in selenium, which has powerful location strategies as compared to the previously discussed strategies.
So it’s very much important that an Automation engineer should be master in the use of XPath and CSS Selector so that they can easily locate the elements in such a situation as when there is no availability of ID or name. Sometime tag name also not working in scenario like when there are many elements with the same tag name and as we know that the linktext will work only when the element has <a> tag, but if the application is supporting multi-language then it will not work because link text is work as the mentioned in the text and if the text changes then it will not work.
I have noticed that most of the automation engineers are do not pay much attention to different location strategies, they depend on the recording and playback option, but when they are going to start any dynamic web page at that time, their scripts are going to fail. And some other testers are using browser plugins like Chropath and few other plugins to retrieve the Xpath for an element. Still, those tools also have some limitations and also like they do not provide the best XPath value for the dynamic contents. So in this post, we are going to discuss XPath in detail, which will help you locate any elements on a webpage.
What is XPath?
XPath is a query language for selecting nodes from a web page using XML expressions, and also, by Using the XPath, we can locate any element on a web page which have HTML Dom structure.
In the above Syntax
- //: It is used to select the current node.
- tagname: It is the name of the tag of a particular node.
- @: It is used to select attributes.
- Attribute: It is the name of the attribute of the node.
- Value: It is the value of the attribute
Types of Xpath
Mainly Xpath is categorized into 2 types, and that are:
- Absolute Xpath
- Relative XPath
Absolute XPath: In this type, the Xpath starts from the root of the HTML pages, but this type of Xpath is not recommended because these types are lengthier and not readable, in the meantime, if there is any small structural changes happen in the application then the Xpath will not work. So Absolute XPath should be used in such cases when you can locate the element using the Relative XPath
Relative XPath: In relative XPath, the path will start from the middle of the dom structure, and it always starts with a double forward-slash (//).
Difference between single ‘/’ or double ‘//’
A single slash at the start of Xpath instructs the XPath engine to look for elements starting from the root node. A double slash at the start of Xpath instructs the XPath engine to search look for matching elements anywhere in the XML document.
But you have to select the Xpath in such a way that:
- It should uniquely identify the element
- You should prepare the Xpath in such a way that you can use the same Xpath in different and subsequent releases.
- The XPath should be selected in such a way that if there are any minor changes in the structure, then also your XPath should locate the element without failing the script.
- The Xpath should be in a readable format
NOTE: Absolute XPaths are faster than the relative XPaths
Locate Element using Known Attribute
Sometimes elements are mentioned in the DOM or web page with some known attributes like name or id, So here we are trying to learn how we can locate such types of elements with the help of those know attributes. But before writing the Xpath, keep in mind that the attribute value is unique and not changed.
Let’s take a Scenario:
Locate the search box of the SoftwareTestingo homepage search box. If you have the HTML code of that search box, that that is:
<input class="search-form-input" type="search" itemprop="query-input" name="s" id="search for-2" placeholder="Search this website">
If you have marked the above HTML, then you can find 3 known attribute which is ClassName, Id, and name, based on those values we can locate the element
NOTE: Third, XPath shall not be used even though it is a valid XPath. Because It will not be a unique XPath. There might be many elements with attribute type=’text’. Hence Selenium will not be able to locate the element uniquely.
Single quotations should be used to enclose the values.
IF there are multiple elements for an XPath?
If with an Xpath, multiple elements are identified, then in that case, if you run your script with that xpath_details, selenium always selects the first element. In that case, to locate a specific element, you can use the sequence number or use some predefined methods like last().
Suppose the table code:
<table id="customers"> <tbody> <tr> <th>Company</th> <th>Contact</th> <th>Country</th> </tr> <tr> <td>Alfreds Futterkiste</td> <td>Maria Anders</td> <td>Germany</td> </tr> <tr> <td>Centro comercial Moctezuma</td> <td>Francisco Chang</td> <td>Mexico</td> </tr> <tr> <td>Ernst Handel</td> <td>Roland Mendel</td> <td>Austria</td> </tr> <tr> <td>Island Trading</td> <td>Helen Bennett</td> <td>UK</td> </tr> <tr> <td>Laughing Bacchus Winecellars</td> <td>Yoshi Tannamuri</td> <td>Canada</td> </tr> <tr> <td>Magazzini Alimentari Riuniti</td> <td>Giovanni Rovelli</td> <td>Italy</td> </tr> </tbody> </table>
From the above table if you want to select the first row and last row then you can sue the below Xpath:
|Alfreds Futterkiste||Maria Anders||Germany|
|Centro commercial Moctezuma||Francisco Chang||Mexico|
|Ernst Handel||Roland Mendel||Austria|
|Island Trading||Helen Bennett||UK|
|Laughing Bacchus Winecellars||Yoshi Tannamuri||Canada|
|Magazzini Alimentari Riuniti||Giovanni Rovelli||Italy|
To select the first row: //tr
To select the last row: //tr[last()]
Locating Elements with known Element and Attributes
If you can able to locate an element using the attributes like Name, id or some other attributes, then you can write the Xpath for an element by following the below syntax
Suppose there is an element on a webpage, and the attributes are like below
Add Example Screenshot [http://pragmatictestlabs.com/2018/05/16/mastering-xpath-for-selenium-test-automation/]
Then you can prepare the XPath to locate the element uniquely by below example
As we have mentioned above, if you can locate the elements using the attributes, then its a good sign to locate the elements, but with those attributes details, if multiple elements are identified, then you can use some predefined XPath function which can help you to locate the elements uniquely.
Types of XPath Functions
There are so many methods are defined in selenium to locate elements on a webpage but we are going to discuss only a few of them which are widely used during writing the automation script, those are
Let’s start how to use the above methods in our automation script one by one, So let’s start with the Contains() method Of XPath.
You can use this method in your automation script when the value of any attributes changes dynamically. For example, there are elements with an attribute id and value abc-123. But the numeric value is changing whenever you visited the application. At that time, you can use the contains() method to easily locate the elements, and it will cont fail your script for the dynamic value change.
Note: If the value is matching with the details of the elements, then it will able to locate the elements in the DOM.
Syntax for Contains():
Syntax: //tag[contains(@attribute, ‘value‘)]
Example: //input[contains(@id, ‘er-messa’)]
I hope with the above example you can understand how to use the contains() method with the XPath. Lets move further and other Xpath functions.
Like the contains() method, it also searches the specified value on the DOM, but the main difference between contains() and starts-with() is starts-with() check the starting text of an attribute whereas contains() will check the value in throughout the attribute. So it’s very helpful when you know that in your element, starting values are not changed, but after a few characters, the value changes randomly. In this case, you can use this method for non-changing attribute values.
Syntax: //tag[starts-with(@attribute, ‘value‘)]
Example: //input[starts-with(@id, ‘user’)]
Now let’s jump to another function text()
You can use this method to locate the element with an exact text match. This method will help when you can observe that the attribute value is changing dynamically with no substantial part of the attribute value that can be used via Starts-with or Contains. in that case, you can use the text() to locate and doing operation on that element.
For locating the element Free Sign Up, you can use the below XPath, its with text(), and by combining contain() and text() method. [https://www.lambdatest.com/blog/complete-guide-for-using-xpath-in-selenium-with-examples/]
Xpath= //button[text()=’Free Sign Up’]
Xpath=//button[contains(text(), ‘Signup’ )]
If you see our two above examples there we have in one example we are trying to use the text() method to identify the element and in the other example where we are trying to locate the same element with the partially matched text with the contains().
At the time of using of Xpath if multiple elements are located with an Xpath then that time if you know the index then you can use the Position() function to locate the elements in the web page and XPath is looks like below
Suppose if we want to locate all the paragraph elements except the paragraph element that is in the first position using position( ) function, we’ve to use position( ) > 1 in the XPath Statement. you can also use the less-than symbol with position() function like this position( )<3.
Note: Always the index is count from top to bottom of the page
Last(): If you don’t know the index of the element but its the last element out of the selected elements then that time you can use the last() function which will select the last element and the syntax is looks something like below
You can also use minus operator (-) with the last() function to locate the elements like below
Using ‘OR’ & ‘AND’
If you remember, you have read about this OR & AND, which are logical expressions. Where in OR logical expression if there are two conditions are there and out of that if any condition is true or both the conditions are true, then you can able to locate the elements.
< input type=”email” placeholder=”Work Email*” name=”email” value=”” class=”form-control sign-up-input-2 ” >
Xpath= //input[@type= ‘email’ or @name= ‘email’]
When we are going to use, AND in that case, both the conditions should match and true, then only the element will be located.
Xpath= //input[@type= ‘email’ and @name= ‘email’]
The index comes to picture when you want to locate an element, and for that, you know the tag details and index of the element. Then, in that case, you can use the index. In the real-time scenario, you can get such cases when you are dealing with the data in a table.
Xpath= //div[@class= ’ col-sm-12 google-sign-form’]/input
Using Chained XPath In Selenium
When by using the existing attributes and functions, if we are not able to locate any element in the DOM that time, we are trying to use multiple Xpaths in a chained form [ using more then one XPath]. for example
<ul class="nav navbar-nav navbar-right"> <li><a href="https://www.lambdatest.com/feature">Live</a></li> <li><a href="https://www.lambdatest.com/selenium-automation">Automation</a></li> <li><a href="https://www.lambdatest.com/blog">Blog</a></li> <li><a href="https://www.lambdatest.com/pricing">Pricing</a></li> <li><a href="https://www.lambdatest.com/support/">Support</a></li> <li class="sign-in"><a href="https://accounts.lambdatest.com/login">Login</a></li> <li class="login"><a href="https://accounts.lambdatest.com/register">Free Sign Up</a> </li> </ul> //ul[@class='nav navbar-nav navbar-right']//li[@class='login']
In the above example, you can say that first, we try to locate the permanent element class for which we have used //ul[@class=’nav navbar-nav navbar-right’] and later we move to our required element which is log in. and all the operation we can do by using multiple Xpath, i hope you can understand this example.
When you are learning XPath, then don’t miss the important concept of Xpath is XPath axes because this will helps you lot to locate the element with the help of writing your Xpath which is a help to locate dynamic elements. Because sometimes, when we are trying to locate a specific element in the DOM, then you may not find the unique attribute(s) or innerHTML that time you have to takes the help of the known elements with unique attribute(s) or innerHTML.
Which we regular daily life, for example, someone asks you about location details in that time we told him about the first location or landmark like [shop, building, street, etc.] which he is aware then from that place we guide him so that he can easily reach to his required location
Similarly, when we try to locate or identify an element in DOM that time, if we are not able to that element using the tagname or some attribute value, then, in that case, we can try to identify by traversing the child/sibling or parent will be an easy approach. Some of the widely used XPath axes are:
What is an Axes View?
Axes view represents the path or the location of the other node concerning the current node.
So the basic rule of axes view is to find a node in the hierarchy which has the constant value for their attribute and marks that node as the current node and calculates the XPath for other node based on that node.
Child Axes view
Suppose your requirement has located an element, but you are not able to locate that element. In that case, you have to find the parent node or the node which you can find easily with some unique attributes. After that, you need to use the child keyword so that all the immediate child nodes will be selected reference to the parent node.
Xpath= //div[@class=’ col-sm-12 google-sign-form’]/child::*
The above syntax will select all the immediate child nodes of that parent node.
Xpath= //div[@class=’ col-sm-12 google-sign-form’]/child::input
If you want to select only the input immediate child nodes of a specific parent node, then you can use another filter with the child keyword to select a specific node.
descendant Axes View [Grand Child & Child Nodes]
When you are going to the descendant keyword, then it will select the immediate child and grandchild nodes of the current node. and the XPath will look something similar like below
Xpath= //div[@class=’ col-LG-3 col-MD-4 col-sm-6 sign-form’]//descendant:: *
After this as per your requirement, you can use the filter to select some specific nodes like below
Xpath= //div[@class=’ col-LG-3 col-MD-4 col-sm-6 sign-form’]//descendant:: input
descendant-or-self Axes view
In the above, we can see that when we use a descendant at that time, we can select the immediate child and grandchild nodes of the current node, but the current node is not selected. Still, when you want to select the current node with the child and grandchild nodes, then that time, you have to use the descendant-or-self keyword.
Xpath= //div[@class=’ col-lg-3 col-md-4 col-sm-6 sign-form’]//descendant-or-self::*
Here you can also the filter option to select some specific node, for example, if you want to select the parent node and input type elements that time you can use
Xpath= //div[@class=’ col-lg-3 col-md-4 col-sm-6 sign-form’]//descendant::input
Note: Whenever you want to deal with the child and grandchild, it is better to use a descendant axes view.
Parent Axes View
As of now, we have different axes view like child, descendant, following, and preceding axes view, and now we are going to look on Ancestor Axces’ view. If you want to select the parent node of the current node at that time, you can use the parent keyword like below
Ancestor [Grand parent] Axes view
When you are going to use the ancestor keyword that it will be going to select all the parent and grandparent nodes of the current node. and the Xpath will look like below
If you want to filter out from the all the select node, then you can use the filters with the ancestor keyword like below
Ancestor-or-self Axes view
In the view, you can able to select the parent and grandparent nodes with the current node also, and the syntax looks like below
Note: using the axes view, you can select any node in a web page or DOM, the only thing you need to find a reference node. So with the help of a reference node, you can able to select any node present anywhere on the web page. This is the main advantage of using the axes’ view.
Following Axes View
The following keyword will select all the node, which is parallel to the current node as well as the child and grandchild node of the parallel node.
Xpath= //input[@name=’ organization_name’]//following::*
You can use the filter with the above node to select any specific node.
following-sibling Axes view
Still, now we have discussed whenever we are going to deal with the child nodes, we need to use the descendant axes view, and whenever we are dealing with the nodes which are parallel with our current node in that case, we are going to sue following axes view. That means the node and the current belong to the same parent.
you can also use filters to locating specific elements.
Preceding Axes view
as we have seen that when we are using the following keyword that time, it only considers those nodes which are at the same level to the current node but below the current node. But when we use the Preceding keyword, it is going to consider all those nodes which are at the same level of the current node but above the current node.
preceding-sibling axes view
preceding-sibling we can use when we want to select all the nodes which are the same level but above the current node. and the XPath will be looks like below: