XPath Functions For Dynamic XPath In Selenium

This Tutorial Explains the Usage of XPath Functions in Identifying the Elements With Examples:

Before automating any website is necessary to identify the object correctly before we can perform any operation on the same. As we know that the easiest way to identify the element is by attributes like ID, Name, Link, Class, or any other unique attribute available with the tag where the element resides.

This is only possible when these attributes are present and/or are unique so that the object is identified correctly.

=> Take A Look At The Selenium Beginners Guide Here.

Dynamic_Effective Xpath in Selenium using Xpath Functions

Overview Of XPath Functions

Let’s discuss the scenario where the attributes are not readily available.

Problem Statement

How do we identify the element if the locators like ID, Name, Class, Link, etc. are not available in the element tag?

This can be understood clearly with the given example:

Login to Twitter

Log In to Twitter

As you can see in the above screenshot, the header “Log in to Twitter” has no attributes attached to it. Having said that, we can’t use any of the locators like ID, Class, Link, or Name to identify this element.

The Firepath plugin of the Firefox tool has generated the below XPath:

//*[@id=’page-container’]/div/div[1]/h1

We won’t recommend the use of the above XPath as the page structure or the id as it may change dynamically. If we do make use of this unstable XPath, we might have to change the XPath more frequently which is more time consuming to maintain. This is one case where we can’t use the generic XPath expression with locators like id, class, name, or link.

Solution

Identifying The Element Using The XPath Functions By Text

As we have the visible text “Log in to Twitter” available with us, we would make use of the following XPath functions to uniquely identify the element.

  1. contains() [By text]
  2. starts-with() [By text]
  3. text()

XPath functions like contains(), starts-with() and text() when used with the help of text “Log in to Twitter” would help us identify the element correctly, and further operations can be performed on the same.

#1) Contains() Method:

Syntax: To find the “Log in to Twitter” web-element, use any of the following XPath expressions that include contains() method.

By Text

  • //h1[contains(text(),’ Log in to’)]
  • //h1[contains(text(),’ in to Twitter’)]

Contains() Method1

Contains() Method2

Note: 1 matching node indicates that the web-element has been identified successfully.

From the above example, it is clear that contains() method doesn’t need the absolute(full) text to identify the element correctly. The partial text is enough to identify it correctly. However, the partial text selected should be unique. The user can easily identify the element even if the orientation of the page is changed with the help of the contains() method.

Please note that even if you use the absolute text “Log in to Twitter” with contains() method, the element would be identified correctly.

#2) Starts-with() method:

Syntax: To find the “Log in to Twitter’” web-element, use the following sample XPath expressions that have starts-with() method.

By Text

  • //h1[starts-with(text(),’Log in’)]
  • //h1[starts-with(text(),’Log in to’)]

Starts-with() method

Starts-with() method2

From the above example, it is clear that the XPath functions starts-with() method requires at least the first word (“Log”) of the visible text to uniquely identify the element. It also works on the partial text and will fail if we don’t include the first word of the partially visible text.

Please note that even if you use the absolute text “Log in to Twitter” with starts-with() method, the element will be identified correctly.

Invalid XPath for starts-with(): //h1[starts-with(text(),’in to Twitter’)]

Invalid Xpath for starts-with()

Note: No matching nodes indicate that the web-element has not been identified.

#3) Text() method:

Syntax: To find the “Log in to Twitter” web-element, use the following XPath expression that has text() method.

Text() method

In this expression, we use the absolute text that is present between the start tag<h1> and the end tag </h1>. If we use text() function with partial Xpath like we do in contains() and starts-with(), we wouldn’t be able to find the element.

Text() method

Invalid Xpath for text():

Invalid Xpath for text

Invalid Xpath for text()

Identifying The Element Using The XPath functions By Attribute

We use the XPath functions (contains or starts-with) with attribute when there are some uniquely identified attribute values available in the container tag. Attributes are accessed using the “@” symbol.

This can be understood clearly with the given example: 

Login to Google

#1) Contains() Method:

Syntax: To uniquely identify the “I’m Feeling Lucky” button element with the help of the XPath function contains() with the help of attribute.

(i) By value attribute:

  • //input[contains(@value,’Feeling’)]
  • //input[contains(@value,’Lucky’)]

Contains() Method for value attribute 'feeling'

Contains() Method for value attribute 'lucky'

From the above images, it is understood that using the attribute value with either “Feeling” or “Lucky” with contains() method will uniquely identify the element. However, it is important to note that even if we use the complete content of Value attribute, it will identify the element correctly.

(ii) By Name attribute:

//input[contains(@name=’btnI’)]

contains() By Name attribute

The invalid case for XPath function with the attribute:

We need to be very careful about selecting the attribute to be used with the contains() and starts-with() method. If the attribute value is not unique, we won’t be able to uniquely identify the element.

Suppose, if we take the “type” attribute when identifying the “I’m Feeling Lucky” button, the XPath won’t work.

“type” attribute when identifying the “I’m Feeling Lucky” button

2 matching nodes indicate that the element has not been identified correctly. Here the type attribute value is not unique.

#2) Starts-with() method:

The starts-with() method with the attribute is very useful when we have to find the elements whose former part of the attribute remains fixed while the later part keeps on changing. This approach is very useful when the objects are dynamically changing the value of its attributes. This can also be used if we want to capture similar kinds of elements.

Go to Facebook login

Inspect the first text box “First Name” and the second text box “Surname” of the Sign-Up form.

Inspect the text box

The first text box “First name” is identified.

text box “First name” identified.

The second text box “Surname” is identified.

In both the text boxes that are identified for the Sign up for Facebook, the starting part of the id attributes remains unchanged.

First name id = “u_0_2”

Surname id=’u_0_4”

This is the scenario where we can use the starts-with() attribute to get all the elements under such type of id attribute. Please note that we’re only taking these two fields for our reference. However, there could be more fields on the screen with id’s that start with “u_0_”.

Starts-with() [By attribute id]

//input[starts-with(@id,”u_0_”)]

Important Note: Here we have used double quotes instead of single quotes. But single quotes will work too with the starts-with method.

starts-with method

11 matching nodes indicate that this XPath has identified all the elements those ids start with “u_0_”. The latter part of the id (2 for first name, 4 for Surname, etc.) determines how we uniquely identify the element.

We can use the starts-with function attribute where we need to collect the similar type of elements in a list, and dynamically pick one of them bypassing the argument in a generic method to uniquely identify the element.

Please follow the below example to use the starts-with function to our advantage.

Sample Code:

/* <strong>Generic Method</strong> */

public void xpathLoc(String identifier){
	//The below step identifies the element “First Name” uniquely when the argument is “2”
WebElement E1=d1.findElement(By.xpath("//input[starts-with(@id,”u_0_”+identifier )]"));
E1.sendKeys(“Test1”);  /* This step enters the value of First Name as “Test 1” */
}
/* <strong>Main Method</strong>*/

public static void main(String[] args) {
		xpathLoc(“2”); --- This step calls the xpathLoc() method to identify the first name.
		}

Note: Eclipse may not allow the use of double-quotes. You may have to resort to different code to make dynamic XPath.

The sample code is given for reference. You may enhance it to fit in all the elements and the operations you want to perform and the values you want to enter (in case of text fields) to make the code more versatile.

Conclusion

This article explained how we can make use of XPath Functions contains(), starts-with() and text() with attribute and text to uniquely identify the elements on the HTML DOM structure.

Below are some of the observations that we can draw for the XPath Functions:

  1. Make use of “contains()” method in XPath if you know the partial constant visible text or attribute.
  2. Make use of “starts-with()” method in XPath if you know the initial partial constant visible text or attribute.
  3. You can also use contains() and starts-with() method with absolute text or attribute.
  4. Make use of the “text()” method in XPath if you are aware of the absolute visible text.
  5. You can’t use text() method with the partial text.
  6. You can’t make use of starts-with() method if the initial text is not used in XPath or if the initial text is constantly changing.

In the next tutorial, we will be learning how to make use of XPath Axes with XPath Functions to further enhance the location of elements on the available webpage.

=> Read Through The Easy Selenium Training Series.