When we are unable to locate elements using standard locators like id, class, name, etc. then we can use an XPath to locate that element. In addition, the use of XPaths enables us to write reusable code. XPaths can be described as XML paths which help us navigate through the HTML structure of a page.
Generally, there are two types of XPaths: absolute and relative. Absolute XPath provides a direct path to an element. Therefore, it goes from the top of the HTML structure to our element. An example of an absolute XPath would look like this:
It starts from the beginning of the HTML structure, and it goes through direct nodes to the desired element. The obvious drawback of this type is that any change in the structure of the website will make the XPath obsolete. In addition, it is important to mention that a single forward slash is used to navigate through direct nodes (/).
On the other hand, relative XPaths can search elements on a webpage starting from anywhere in the HTML DOM structure. It uses a double forward slash (//), which searches elements anywhere on the webpage. An example of a relative XPath:
//div[@class = 'container main-content’]
In this article, we will be focused on relative XPaths. Before diving deeper into XPaths, let us explain its basic structure. XPaths start with a double forward slash (//). There are three main elements of an XPath: tag, attribute and value. Tag refers to the HTML element that we want to select (div, img, a, span, table, etc.). Tags have different attributes depending on the structure of the webpage (class, name, id, etc.). Therefore, we need to provide the value of the specific tag attribute in order to be able to find that specific element.
//tag[@attribute = ‘value’]
Other than the basic structure that we just explained, there are the following options in XPath that come in handy for test automation:
The Contains option enables us to write XPaths for elements whose attributes are dynamic. Imagine that the name of an element changes, but a certain part of the name (‘instance’) is always constant in the class name. We could write the following XPath in order to select an element:
- OR & AND
We can use the OR keyword in order to select a specific element even if one of the two provided attributes are true. In the XPath below, it will find the div element no matter which of the two conditions are satisfied:
//div[@data-number-size = '62' or @class = 'number standard’]
If we use AND keyword, the element will not be found unless both conditions are satisfied: An example of an XPath with AND keyword:
//div[@data-number-size = '62' and @class = 'number default']
- Starts with
The ‘Starts with’ option enables us to select dynamic elements whose beginning attribute value is always the same. Imagine that there is an element with a class name that is dynamic (form-control has-spinner wpcf6), and the number in the end changes on the refresh (wpcf7, wpcf10, wpcf11, etc.). However, the preceding part of the class name is always the same. Therefore, we can write an XPath like this to select this element:
//input[starts-with(@class, 'form-control has-spinner wpcf')]
- Text() function
We can also find elements based on the text displayed on the webpage using the Selenium built in function text(). This XPath will find the element which displays text ‘Home’.
//ul[@class = 'menu menuopen']//a[text() = ‘Home']
Following method starts to locate elements after the given parent node. An example of the following method is:
//ul[@class = 'menu menuopen’]//following::li
In this case, it first finds the parent element //ul[@class = ‘menu menuopen’]. Then, it finds all li elements after that.
Ancestor keyword selects all ancestor elements (parent, grandparent, etc.) of the current node that we provide. In the example below //ul[@class = ‘menu menuopen’] is the current node, and the following part selects all parent div elements.
//ul[@class = 'menu menuopen’]//ancestor::div
This keyword allows us to select all child elements of the current node. An example of an XPath that selects child elements of a current node:
//ul[@class = 'menu menuopen’]//child::li
This selects all nodes that come before the current node. An example of selecting preceding divs of the current node:
//ul[@class = 'menu menuopen’]//preceding::div
Siblings are the same level of the current node. This function allows us to select the following siblings of the current node.
//li[@id = 'menu-item-15362']//following-sibling::li
It allows us to select the parent element of the current node.
//ul[@class = 'menu menuopen’]//parent::div
This keyword allows us to select all descendants of the current node. The XPath below will select all li elements that are descendants of the ul element.
//ul[@class = 'menu menuopen’]//descendant::li
“XPath in Selenium” Tech Bite was brought to you by Hasan Okanović, Junior Test Engineer at Atlantbh.
Tech Bites are tips, tricks, snippets or explanations about various programming technologies and paradigms, which can help engineers with their everyday job.