Constructing XPath's Manually
Before you read this you may want to see:
Main Article
XPath is a locator that identifies an element in the Document Object Model(DOM) and/ or on the User -Interface. Dynamic applications have element locators that change constantly and locator with Id, CSS, link, Name etc might not give successful results. To handle such situations of locators that change dynamically, you may have to write custom XPath.
This document will help you understand how a dynamic element is identified and how to write custom XPath.
Please refer to the below, screenshot to understand how dynamic ID may look like
In the above screenshot the User-Interface element “ Student McStudent”, has an Id(Salesforce Id) that is dynamic and each time the test is executed the order might not be the same. In such cases, you have to write a custom XPath for changing UI elements.
Basic Xpath
//html/body/div[1]/header/div/div[2]/div[3]/div/div/a[1]
From the above XPath example
- // indicates starting of the DOM or HTML Document
- / indicates traversing to next tag/element/child element
- [n] indicates index of occurrence of element [where n=1,2,3….]
The XPath can be copied from UI by using Inspect Element/firebug/fire-path and follow below process:
- Install firebug add-on on Firefox browser.
- Press F12 pr by using inspect element select required UI element.
- In DOM, right click on the selected area and you will find an option copy XPath
The below screenshot helps to understand how XPath is formed
Writing XPath will be easy if you understand tree structure of DOM tags. XPath can be written in different ways.
Types of XPaths:
XPaths can be categorized into
- Relative XPath
- Attribute XPath
Relative XPath:
The basic representation of a relative XPaths is shown below:
//html/body/div[1]/header/div/div[2]/div[3]/div/div/a[1]
Relative XPaths work best for static applications and will not work for dynamic applications.
Attribute XPath:
XPaths with attributes such as Id, text, class, style etc, of a UI element are referred to as XPath attribute. To write XPath with an attribute it should be prefixed or appended with "@"Example; @Id,@class, @style etc,.
1. XPath for Text:
In the above screenshot to locate the ' th' tag “Application Number” the XPath would be
Syntax: //TAGNAME[contains(UI ATTRIBUTE(),'YOUR TEXT HERE’)] Example: //th[contains(text(),’Application Number’)]
2. XPath for class:
In the above screenshot to locate “Application Number” text using its class name the XPath would be
Syntax: //TAGNAME[contains(@class,’CLASS NAME’)] Example: //th[contains(@class,'zen-deemphasize')] Syntax: //TAGNAME[@class=’ CLASS NAME’]
To handle any extra spaces with in the class name, it is recommended to use XPath with 'contains' keyword.
3. XPath Position:
From the screenshot to locate “Application Number” text using its position below is the XPath
Syntax: //PARENT TAG/REQUIRED TAGNAME[Index] Example: //tbody/tr/th[1]
XPath Axes:
In the above picture, the first 'div ' tag is parent tag, for this, there are two child tags which are also siblings. To traverse from top element tag until bottom element tag use ' following::' and from bottom element tag until top element tag use ' preceding::' these are called XPath Axes.
Below are also few other XPath axes:
- following-sibling::
- preceding-sibling::
- child::
- parent::
- ancestor::
Advanced XPath
For dynamic 'class' Names:
If 'th' tag class is dynamic, then consider its parent or child elements which will be unique and start XPath from it.
Syntax: //GRAND PARENT TAG// REQUIRED TAGNAME[contains(UI ATTRIBUTE(),’YOUR TEXT HERE’)] Example 1: //div[@class='hotListElement']//th[contains(text(),’Application Number’)]
Note: To traverse to any child tag use “//”, since 'th' tag is child tag of 'div'. In the above XPath //is used.
Example 2: //div[@class='hotListElement']//following::th[contains(text(),’Application Number’)]
For dynamic 'Tag' Names:
For 'tag' names that change dynamically then use * instead of specifying tag name.
Example: //*[@class='hotListElement']//th[contains(text(),’Application Number’)]
For exact 'text':
XPath with 'contains text' would identify the text even if the text that is part of a sentence.To find the exact match of the text use period (.) in the XPath.For example text is “Application Number” XPath //th[contains(text(),’Number’)] or //th[contains(text(),’Application’)] works but to match exact text use period XPath
Example: //th[.=’ Application Number’’]
Logical Operators in XPath:
You can also use logical operators will writing custom XPath's. Following are the logical operators that works only if these conditions match.
Example: //TAG NAME[((contains(text(),’YOUR TEXT’) and (contains(text(),’YOUR TEXT’))] Example: //TAG NAME[((contains(text(),’YOUR TEXT’) or (contains(text(),’YOUR TEXT’))] Example: //TAG NAME[.>’SOME NUMBER’]
Example for 'Not' In XPaths: //TAG NAME[(contains(@class,'typeA') or contains(@class,'typeB')) and not(contains(@class,'ng-hide'))]
Xpath with 'Following' and 'Preceding':
Usually following and preceding works for siblings or locating to tags that are present in the another parent tag
In the above image to traverse from first “div” tag to its next sibling “div” tag and vice versa below are the XPaths
Example for 'following': //div[@class=’bPageTitle’]/following::div[@class=’filterOverview’] Example for 'Preceding': //div[@class=’filterOverview’]/preceding::div[@class=’bPageTitle’]
Dynamic XPaths that change as per the script/Data File variables
In case if you want to use the same XPath for different texts or inputs then store inputs into some variable(s) and use in the XPath as shown below
//div[@class=’${ClassName}’]//th[contains(text(),’${TextName}’)]