Ultimate XPath Writing Cheat Sheet Tutorial with Syntax and Examples

Top 20 Ways to Write Ultimate XPATH for ANY Type of Web Element (XPATH will never be invalid):

A web application is made up of different types of web elements such as web element for a button to click on, input web element to type text, drop-down, radio buttons, etc.

These web elements are also called tags or nodes.

When it comes to automating web applications, it starts with writing an automation script that will find the web element, perform an action on it such as, click on a button, enter text into input box, select a checkbox, select a radio button, scroll up or down and finally verify the expected behavior in turn of the action.

20 WAYS TO WRITE XPATH FOR ANY TYPE OF WEB ELEMENT

What is XPath and How It Look Like?

Finding an element is like finding someone’s house on the map. The only way we can find a friend’s home without any external help is that we should have a map and know what to find (house).

In order to put this analogy in our case, the map will be used as DOM (HTML tags, JavaScript, etc.) where all the web elements exist, along with the specific web element that we want to find.

Once the unique address or path of an element is found, automation script will then perform some actions on it based on the test scenario. For Example, you want to verify the URL of the page which opens up after clicking on a button.

However, it is not straight forward to find a unique address/path of a web element as there might be similar tags, same attributes values, identical paths making by it hard to create exact unique address to a web element called “XPATH”.

Here, we’ll deep dive into some great and effective techniques to generate valid and unique XPATH for any type of web element.

Recommended Read => Identify Web Elements Using XPath in Selenium

Sometimes you can easily create XPaths using browser extensions but in my automation testing career, I have faced countless situations where traditional browser extensions don’t work and you must come up with your own customized XPaths using your own creativity. I’m sure that you have or will face similar situations.


Recommended Tool:

#1) Ranorex Webtestit

Ranorex Webtestit Logo

Ranorex Webtestit delivers out-of-the-box web test automation for Selenium or Protractor, using Java or TypeScript: no assembly required. Save time with automatic creation of Page Objects, UI element locators, and boilerplate code; built-in test reporting, and more. Distribute cross-browser tests to local WebDriver endpoints, a Selenium Grid, or a cloud-based provider. [Try it free today!]

=> Visit Ranorex Webtestit Website


In this tutorial, we will take a look at the 20 best ways on how to create ultimate XPath for a web element in such as way that even when your code is changed, your XPath will stay valid all the time (unless developer rewrites the entire feature/module).

By knowing all these techniques, you will become a master of writing your own XPath and would be able to write killer XPaths with very few chances of becoming invalid.

First, let’s start with understanding XPath syntax and define each of its parts.

The below image will show how XPath will look along with a description of each part:

XPATH Syntax

  • // : Select current node such as input, div etc.
  • Tagname: Tagname of the web element/node
  • @: Select attribute
  • Attribute: Attribute name of the node/particular web element
  • Value: Value of the attribute

Just want to share a couple of tips here that 80% of time my automation test script failed because of XPath. This caused by either there are multiple web elements for the provided XPath or XPath is not valid or the page has not been loaded yet.

So, whenever your test case fails:

  1. Copy your XPath.
  2. Search it in the Browser (F12 or developer tool window) in the DOM to verify if it is valid or not (See the below image).

F12 Window

Pro Tip 1: Make sure it is unique and no other web element appears when you search twice in the DOM.

Pro Tip 2: Sometimes there is a timing issue, which means that your web element/page is not yet loaded while the script was looking for it, hence add some wait time and retest.

Pro Tip 3: Try to print the entire DOM before searching for the web element. This way you can tell by looking into Console if your web element exists in the DOM or not.

Before we dive deep into XPath look up, one important thing that I want to share is that if you have direct access to the development team or if your team is located where you are, then ask your development team to provide you with unique IDs in each web element or at least the ones that you want to use for Automation and this will save a lot of your time.

If this is not the possibility, then you might need to use your creativity and come up with your own customized XPaths and which is what we are going to learn now.

Top 20 Ways to Write XPath for Any Web Element

Let’s deep dive into creating the top 20 ways to a killer XPath.

#1) Reverse Lookup

Let’s say that you want to click on a button and there is a similar button. Both buttons have id attributes, but they are dynamic and none of the attributes are unique in both the button elements.

In the below scenario we want to click on the “Setting” button of the “Test Interactive”.

Revers Look up

Code

Revers Look up code

If you look at the “Setting” buttons, both the codes are similar. By using traditional ways such as id, name, value, contains, etc., none of them will work for example.

//*[contains(text(), ‘Setting’)], This will result in two web elements. Hence it is not unique.

So here is the final strategy,


>> First, Find the closest tag that is unique and in this case, it is <widget id=’rcTest’………>

XPATH: “//*[@id='rcTEST']

>> Second, Find the closest web element to the intended web element which in this case contains(text(), ‘TEST Interactive’). Now we are in the same <DIV> where the ‘Setting’ button exists but to click on it, we first need to go to the main <DIV> by using double dots as shown below.

XPATH: “//*[@id='rcTEST']//*[contains(text(), 'TEST Interactive')]/..

Find the closest web element

>> As you can see, we are in the <DIV> level which has the second web element as the ‘Setting’ button. This <DIV> has two buttons in it and we want to go to the second button which is the ‘Setting’ button. By adding ‘/button[2]’ at the end we can get our unique XPATH for the ‘Setting’ button as shown below.

adding ‘/button[2]’

Final XPATH:

“//*[@id='rcTEST']//*[contains(text(), 'TEST Interactive')]/../button[2]”

Here is another way to generate if you think they might change the web element type from “button” to something else.

“//*[@id='rcTEST']//*[contains(text(), 'TEST Interactive')]/..//*[contains(text(), 'Setting')]”

or using “following-sibling”

“//*[@id='rcTEST']//*[contains(text(), 'TEST Interactive')]/following-sibling::button”

#2) Using Variables and Custom Values

Let’s say that there is a web application that has FTP (“File Transfer Protocol”) feature to upload/download files and you have a test case to download a specific file by clicking on the download link.

First, we can define the file name that we are looking for as a variable.

String expectedfileName = “Test1”;

Now using the XPATH we can find the actual file name.

“String actualFileName = WebDriverAccess.getDriver().findElement
(By.xpath("//*"+fileName +"/tr/td[1]")).getAttribute("title");”

In the above XPath, …‘/tr/td[1].getAttribute(“title”)’ will go to the specific row and first column and get the value of the title attribute. We can store the actual file name into another variable.

Once we have both the expected and actual file names, we can compare both and if both match we can simply click on its download link.

(if acutalFileName == expectedFileName) {
 WebDriverAccess.getDriver().findElement(By.xpath("//*"+fileName +"/tr/td[4]")).click();
}

We can also create a loop through each row and keep verifying the file name until you find it.

Loop(int count < 30)
{
String actualFileName = WebDriverAccess.getDriver().findElement
(By.xpath("//*"+acutalFileName +"/tr[" + count + "]/td[1]")).getAttribute("title");
(if acutalFileName == expectedFileName) {
WebDriverAccess.getDriver().findElement(By.xpath("//*"+fileName +"/tr/td[4]")).click();
}
Count++;
}

#3) Using “XML” tags, “AND” etc

We can generate unique XPATH using customized tags plus add other conditions.

For Example, let’s say our intended web element exists in the main <address> tag, and there are multiple address tags, but you want to find only a specific one. All address tags have a class attribute, thus we can start with.

// address[@class='ng-scope ng-isolate-scope']

We noticed that our intended web element is in a <DIV> tag which has some text called ‘Testing’.

// address[@class='ng-scope ng-isolate-scope']//div[contains(.,'Testing')

We figured out that there are multiple web elements found as a result. Hence to make it more unique, we can add the other conditions such as “id” which will finally point us to the web element that we are looking for.

 // address[@class='ng-scope ng-isolate-scope']//div[contains(.,Testing') and @id='msgTitle']

#4) Using Attributes and Table XPATH

Let’s assume that we want to type into a web element that is placed inside a table and the table is placed inside a form element.

We can find all the forms inside DOM with the name ‘myForm’.

“//*[@name='myForm']”

Now in all the forms find the table with id ‘tbl_testdm’.

"//*[@name='myForm']//table[@id='tbl_ testdm’]”

Within the table go to a specific row and column.

"//*[@name='myForm']//table[@id='tbl_ testdm’]/tbody/tr/td[6]/”

Within the cell, if there are multiple inputs, then find an input where value = ‘Open RFS’, and this will give us the final XPath of the field.

 //*[@name='myForm']//table[@id='tbl_ testdm’]/tbody/tr/td[6]/ input[@value='Open RFS']"

#5) Using Attributes, Tables, and Text

Assume that your intended web element lies in the Panel Table and has some common text.

First start with a panel having a unique attribute which in this case is ‘TITLE’.

//*[@title=’Songs Lis Applet']

Now navigate through all the table tags.

//*[@title=’Songs Lis Applet']//table

Within all the tables find the column which has text ‘Author’.

Final XPath would be like:

 //*[@title=’Songs List Applet']//table//td[contains(text(),'Author')]

#6) Generating XPATH Using Nested Attributes

Target web element’s XPath can also be generated using the nested attributes. For Example, in this case, it’ll look for a specific attribute across DOM and then look for another attribute within it.

 //*[@id='parameters']//*[@id='testUpdateTime']")

#7) XPath Generation by Combining Attributes, Divs, and Button

For Example, in the below XPath, I was able to find the target web element by using an id (relative XPath), some div tags and a button.

“//*[@id='MODEL/PLAN']/div[1]/div[2]/div[1]/div[1]/widget/section/div[1]/div/div[1]/div/div/button[1]"

#8) XPATH Generating using CONTAINS, REVERSE LOOKUP, etc.

Once I had a drop-down with no direct identification. I had to use CONTAINS, REVERSE, DIVs, attributes to come up with the final XPATH as shown below.

//*[contains(text(),'Watch Dial)]/../div/select[@data-ng-model='context.questions
[subqts.subHandleSubId]']"),

#9) XPath Generation using Relative, CONTAINS, REVERSE, FOLLOWING SIBLING, etc.

I had a situation where the application displays a graph, and each graph value had to be validated. But, unfortunately, each value didn’t have any unique identification, so I have come up with the final XPATH as shown below for one graph value which combines relative, contains, reverse, following-sibling and div tags.

 //*[@id='RESEARCH/PLAN']//*[contains(@id, 'A4')]/../../following-sibling::div[1]/div[1]/span[1]/span[1]

#10) XPath Generation using Attributes, Contains, Reverse, Preceding-Sibling, Divs, and Span

Once I had to validate different Alarm data and each alarm value has been displayed based on a specific calculation or timings. In order to capture each value, I had to come up with the below XPATH that uses attributes, contains, reverse, preceding-sibling, divs, and span tags.

 //*[@id='ALARMDATA']//*[contains(@id, 'AFC2')]/../../preceding-sibling::div[1]/div[1]/span[1]/span[1]

#11) Using Attributes, XML Tags etc.

In the below XPATH, attributes and XML tags, a sequence is used to come up with the final unique address of a web element.

//*[@id='RESEARCH/REVIEW']
//widget/section/div[1]/div/div[2]/div[1]/div[3]/div[1]//span[@class='details']

#12) XPath Generation by not Looking into the Entire Page but Looking into all the Links instead and Contains

The below XPath would look for only links in an entire page which contain the text as “Parameter Data Manual Entry”.

//a[contains(.,'Parameter Data Manual Entry')]

#13) Using Contains and Attributes

 //*[contains(@style,'display: block; top:')]//input[@name='daterangepicker_end']

#14) Using Attributes, Following Siblings and Descendant

 //*[@id='dropdown-filter-serviceTools']/following-sibling::ul/descendant::a[text()='Notepad']

#15) Using Attributes, Following Siblings, Descendant, and Text

 //*[@id='dropdown-filter-service tools']
/following-sibling::ul/descendant::a[text()='Trigger Dashboard']

#16) Using Header and Text

If the web element is a header with some specific text, then the XPath could be as shown below:

//h3[text()='Internal Debrief']

#17) Using Header Text, Following Siblings, Path, etc.

//h3[contains(text(),'Helium Level')]/following-sibling::div/label/input

#18) Using Attributes, Contains and Preceding Siblings

Once I had a span which didn’t have any unique attribute, I had created XPATH by combining absolute, Contains, preceding siblings and another absolute path.

//div[div[p[contains(text(),'Status')]]]/preceding-sibling::div/div/span[3]/span

#19) Looking for drop-down by using Id Attribute, some Specific Text, and Reverse Lookup

//*[@id='COUPLING']//*[contains(text(),'COUPLE Trend')]/../div/select

#20) Combining “id” Attribute and looking for a link with Specific Text

//*[@id='ffaHeaderDropdown']//a[contains(text(),'Start Workflow')]

Conclusion

When it comes to writing a killer XPATH, it really depends on how well you understand and analyze the code. The more you understand the code the more will be the number of ways that you’ll find in writing effective XPATHs.

The first step in writing XPath is to find the closest unique web element to your target web element and keep getting closer using different techniques discussed above such as attributes, DIVs, following, contains, etc.

In the end, we would say this again that it’ll really make your life easier if you request your development team to add unique ids in all web elements that you are interested in.

Whenever a sprint cycle or work on new requirement starts and the team is shared with new mockups, I always go through all the mocks ups and think about potential automation test cases in my mind, prepare a list of all potential web elements that will be used in automation tests and prepare my own ids.

Once a list of all the web elements along with my suggested ids is completed, I would share it to developer beforehand to be used in the development code. This way, I would always get unique IDs by making my XPATH writing battle easy.

Below is a combined list of different ways to write XPATHs:

  1. “//*[@id='rcTEST']//*[contains(text(), ‘TEST Interactive')]/../button[2]”
  2. “//*[@id='rcTEST']//*[contains(text(), ‘TEST Interactive')]/..//*[contains(text(), ‘Setting')]”
  3. “//*[@id='rcTEST']//*[contains(text(), ‘TEST Interactive')]/following-sibling::button”
  4. “String actualFileName = WebDriverAccess.getDriver().findElement(By.xpath(“//*”+fileName +”/tr/td[1]”)).getAttribute(“title”);”
  5. WebDriverAccess.getDriver().findElement(By.xpath(“//*”+fileName +”/tr/td[4]”)).click();
  6. “// address[@class='ng-scope ng-isolate-scope']//div[contains(.,Testing') and @id='msgTitle']”
  7. “//*[@name='myForm']//table[@id='tbl_ testdm’]/tbody/tr/td[6]/
  8. input[@value='Open RFS']”
  9. “//*[@title=’Songs List Applet']//table//td[contains(text(),'Author')]”
  10. “//*[@id='parameters']//*[@id='testUpdateTime']”)”
  11. “//*[@id='MODEL/PLAN']/div[1]/div[2]/div[1]/div[1]/widget/section/div[1]/div/div[1]/div/div/button[1]”
  12. “//*[contains(text(),'Watch Dial)]/../div/select[@data-ng-model='context.questions[subqts.subHandleSubId]']”),”
  13. “//*[@id='RESEARCH/PLAN']//*[contains(@id, ‘A4')]/../../following-sibling::div[1]/div[1]/span[1]/span[1]”
  14. “//*[@id='ALARMDATA']//*[contains(@id, ‘AFC2')]/../../preceding-sibling::div[1]/div[1]/span[1]/span[1]”
  15. “//*[@id='RESEARCH/REVIEW']//widget/section/div[1]/div/div[2]/div[1]/div[3]/div[1]//span[@class='details']”
  16. “//a[contains(.,'Parameter Data Manual Entry')]”
  17. “//*[contains(@style,'display: block; top:')]//input[@name='daterangepicker_end']”
  18. “//*[@id='dropdown-filter-serviceTools']/following-sibling::ul/descendant::a[text()='Notepad']”
  19. “//*[@id='dropdown-filter-serviceTools']/following-sibling::ul/descendant::a[text()='Trigger Dashboard']”
  20. “//h3[text()='Internal Debrief']”
  21. “//h3[contains(text(),'Helium Level')]/following-sibling::div/label/input”
  22. “//div[div[p[contains(text(),'Status')]]]/preceding-sibling::div/div/span[3]/span”
  23. “//*[@id='COUPLING']//*[contains(text(),'COUPLE Trend')]/../div/select”
  24. “//*[@id='ffaHeaderDropdown']//a[contains(text(),'Start Workflow')]”

Hope this informative article would have enriched your knowledge on writing XPaths.

If you have more ideas, please share in comments!

Recommended Reading


3 thoughts on “Ultimate XPath Writing Cheat Sheet Tutorial with Syntax and Examples”

  1. Thanks so much for sharing your knowledge to other techies…..You are one in a million with a big heart by sharing freely.

  2. Thank you for the post. I think no one can’t find the best tutorial other than this one. You have explained everything in a way that everyone can easily understand. It is quite transparent and coherent. For the first time here, I have realized these 20 ways to write the XPath. I usually practice 2 or 3 methods posted here, but it is wondrous to become familiar with bounteous ways. I use this opportunity to appreciate you for the help.

Leave a Comment