Sunday, September 30, 2018

XPath Explained

To become an excellent selenium automation engineer, one must become master in locating dynamic web elements. As the attributes of dynamic web elements get changed dynamically when refreshed or on dynamic operations, it’s almost impossible to find the web elements with the help of usual locators such as id, class, name, etc. XPath is one of the most powerful location strategies used in selenium which makes us comfortable enough to locate dynamic web elements and elements without id or name effectively.

Choosing the right and effective XPath is very important and we cannot always rely on tools for the best decisions. In this article, we are going to discuss the XPath and various XPath expressions that are capable of locating complex and dynamic web elements on the web page without the help of any tool.

What is XPath?

XPath is defined as XML path. As XPath is a query language which is based on the tree representation of the XML document, it provides the ability to navigate around the XML tree and locate individual elements, attributes or any other node of the XML document. XML and HTML are like siblings. They have a very similar structure and as a result XPath can be used to query HTML document too.

Syntax for XPath:

The syntax for XPath is very simple and easy to understand. Standard syntax for constructing XPath is given below:
XPath = //tag[@attribute='value']
// : used to select the desired node.
tag : tag of that particular node.
@ : used to select attribute.
attribute : name of the attribute.
value : value of the attribute

For example:
//li[@id = 'ogbkddg:4']
XPath in Selenium WebDriver
Here,
  • //li selects all 'li' node
  • @id = 'ogbkddg:4' selects the attribute which has 'ogbkddg:4' as attribute id value.
So, //li[@id = 'ogbkddg:4'] selects all the 'li' node which has 'ogbkddg:4' as attribute id value. In our case, we have only one matching node for the query.

XPath can be created in two ways:

  1. Absolute XPath
  2. Relative XPath
Types of XPath in Selenium WebDriver

Absolute XPath

The easiest way of finding the XPath is to use the Browser Inspector tool to locate an element and get the XPath of it.

Absolute XPath in Selenium WebDriver

Absolute XPath begins with the root of the HTML pages and is prefixed with a ' / '.

For example:
/html/body/div[1]/div[2]/div[1]/form/div[1]/div/div[1]/div/div/input[1]

Pros

  • It is the easiest way to locate an element.
  • It identifies the element very fast

Cons

  • It is not readable as it can be very lengthy
  • It is very delicate as a minor structural change can make it useless.
Let's discuss the second con of Absolute XPath below:

<html>
   <body>
      <table>
         <tr>
            <th>Column One</th>
            <th>Column Two</th>
         </tr>
      </table>
   </body>
</html>

For the above HTML document if user wants to get the second 'th' then the Absolute XPath will be
/html/body/table/tr/th[2]
Now if we add a new tag between the body and table as below:

<html>
   <body>
      <p>Paragraph One</p>
      <table>
         <tr>
            <th>Column One</th>
            <th>Column Two</th>
         </tr>
      </table>
   </body>
</html>

then the first path will not work as 'p' tag is added in between the body and table. In this case, we have to rewrite the XPath as below:
/html/body/p/table/tr/th[2]

Relative XPath

A Relative XPath is the path which starts from the node of our choice and is prefixed with a ' // '. It doesn't need to start from the root node.

For example:
//span[@class='Email']

Pros

  • It starts from the node of our choice
  • It is readable and shorter than Absolute XPath
  • It works even after structural change

Cons

  • It takes more time to identify element as we specify the partial path
  • If there are multiple elements for the same path, it will select the first element that is identified
Let's take a look at a Relative XPath below:
//li[@id = 'ogbkddg:4']
Relative XPath in Selenium WebDriver

Here, //li[@id = 'ogbkddg:4'] is a Relative XPath and as we can see it did not start from the root node and started from the node of our choice. It is also short and very easy to read. Even if there is any kind of structural change, it will work just fine.

Choosing XPath Wisely

We should be very careful and should consider followings while constructing an XPath.
  • Unique
  • Descriptive
  • Unlikely to change
  • Shorter in length
  • Valid even after changes to a page

Smart XPaths

1. Basic XPath (Tag, Attribute & Value)

i. Single Attribute:

Single attribute XPath uses one attribute to locate an web element.

Syntax:
//tag[@attribute = 'value']
Example:
//input[@id = 'user-message']
This would select the input element nodes which has 'user-message' as it’s id attribute value.
//*[@id = 'user-message']
This would select all element nodes in the whole document which has 'user-message' as it’s id attribute value.
.//*[@id = 'user-message']
This would select all element nodes descending from the current node which has 'user-message' as it’s id attribute value.

Let's get a clear view with the below example:
//li[@id = 'ogbkddg:4']
How do I extract an attribute's value through XPath?

Here, //li[@id = 'ogbkddg:4'] selects all the 'li' node which has 'ogbkddg:4' as it's attribute id.

ii. Multiple Attribute:

Sometimes it may not be possible to locate an element with a single attribute. In the real world, we have a similar issue. We cannot locate a person just by his/her first name or last name. We have to use a combination of first name and last name to locate a person without making any confusion. A similar technique is used in selenium for locating elements.

Syntax:
//tag[@attribute1='value1'][@attribute2='value2']…[@attributeN='valueN']
Example:
//input[@class='button'][@type='submit'][@value='LOGIN'][@name='Submit']
Let's get a clear view with the below example:
//div[@class = 'ctr-p']
After using the above XPath in 'google.com', we will get two nodes in result.

XPath in Selenium WebDriver

Now if we want to get a single node than we can simply add another attribute in the above XPath and get the desired result. We will use below XPath:
//div[@class = 'ctr-p'][@id = 'footer']
Generating XPath With Multiple Attribute

Here we can see after adding new attribute we are able to select our desired node only. To get the other node we can just simply use:
//div[@class = 'ctr-p'][@id = 'viewport']
XPath Query With Multiple Attribute

2. Chained XPath

We can create a chain of multiple Relative XPath declarations with ' // ' double slash to find an element location as shown below:

Syntax:
//tag[@attribute='value']//tag[@attribute='value']
Example:
//div[@class='form-group']//input[@id='user-message']
Let's get a clear view with the below example:
//li[@class = 'gb_T']//span[@class = 'gb_Z']

Here, //li[@class = 'gb_T']//span[@class = 'gb_Z'] selects all the 'li' elements which contains 'gb_T' as attribute class value and then selects all the 'span' elements which contains 'gb_Z' as attribute class value. //span[@class = 'gb_Z'] selects only those 'span' elements which are the decedent of the 'li' elements selected by //li[@class = 'gb_T'].

3. XPath Using 'text()':

text() is a method in XPath expression which is used to form a locator based on the text available on a webpage

Syntax:
//tag[text()='exact text']
Example:
//a[text()='About']

4. XPath Using 'contains()':

When an attribute of an element is dynamic then one can use 'contains()' to select the element by using the constant part of the attribute of that web element.

Syntax: 
//tag[contains(@attribute, 'value')]
Example:
XPath = //tag[contains(@name, 'btnClk')]
It searches 'btnClk' for all name attributes in the DOM.
XPath = //tag[contains(text(), 'here')]
It searches the text 'here' in the DOM.
XPath = //tag[contains(@href, 'google.com')]
It searches 'google.com' link in the DOM

Let's get a clear view with the below example:
//span[contains(@class, 'gb_')]
XPath Using 'contains()'

Here, //span[contains(@class, 'gb_')] searches all the 'span' elements which contains 'gb_' as attribute class value.

Another example:
//a[contains(text(), 'ac')]
'contains()' & 'text()' function in XPath

Here, //a[contains(text(), 'ac')] searches all the 'a' elements which contains 'ac' as attribute text value.

5. XPath Using 'starts-with()':

starts-with() method is used to identify an element when one is familiar with the attribute value of an element. This method checks the starting text of an attribute. It is very handy to use when the attribute value changes on refresh or any operation on the webpage. We can also use this method to find the element whose attribute value is static.

For example:

Suppose the ID of particular element changes dynamically like:
  • Id="message1"
  • Id="message2"
  • Id="message3"
Here we can see that the initial text is same. In this case, we can use start-with().

Syntax:
//tag[starts-with(@attribute, 'value')]
Example:
//input[starts-with(@id, 'user-message')]
 In the above example, XPath finds those element whose 'ID' starting with 'user-message'.

6. XPath Using 'and':

'and' expression uses two conditions and both conditions must be true to locate a web element. It will fail to locate an element if any of the conditions is false.

Following explanation of  'and' expression will help us to understand this topic briefly.

Two conditions with 'and' expression such as A and B returns the result-set shown below:

A
B
Result
False
False
False
True
False
False
False
True
False
True
True
True

Syntax:
//tag[@attribute='value' and @attribute='value']
Example:
//div[@class='form-group' and @id='user-message']
Let's get a clear view with the below example:

When Condition One and Condition Two both are False then no result is found:
//div[@class = 'spch_' and @id = 'spch_']

When Condition One is False and Condition Two is True then no result is found:
//div[@class = 'spch_' and @id = 'spchc']

When Condition One is True and Condition Two is False then no result is found:
//div[@class = 'spchc' and @id = 'spch_']

When Condition One and Condition Two both are True then result is found:
//div[@class = 'spchc' and @id = 'spchc']

7. XPath Using 'or':

'or' expression uses two conditions and one of the two conditions must be true to locate a web element. It will fail to locate an element if both the conditions are false.

Following explanation of  'or' expression will help us to understand this topic briefly.

Two conditions with 'or' expression such as A or B returns the result-set shown below:

A
B
Result
False
False
False
True
False
True
False
True
True
True
True
True

Syntax:
//tag[@attribute='value' or @attribute='value']
Example:
//div[@class='form-group' or @id='user-message']
Let's get a clear view with the below example:

When Condition One and Condition Two both are False then no result is found:
//div[@class = 'spch_' or @id = 'spch_']

When Condition One is True and Condition Two is False then result is found:
//div[@class = 'spchc' or @id = 'spch_']

When Condition One is False and Condition Two is True then result is found:
//div[@class = 'spch_' or @id = 'spchc']

When Condition One and Condition Two both are True then result is found:
//div[@class = 'spchc' or @id = 'spchc']

Conclusion

Hopefully, the above explanation helped you to understand the XPath in selenium web driver. Please let me know in the comment section below if you find anything difficult to understand. I'll try my level best to help you.

1 comment: