XPath
XPath
Introduction
Selenium test automation engineers must be comfortable in locating elements in web pages.
XPath and CSS are the most powerful location strategies used in Selenium as compared to
other location strategies (id, name, className, linkText, partialLinkText and tagName )
Mastering XPath and/or CSS is essential for the Selenium test automation engineers to locate
dynamic web elements, elements without ids or names and elements with dynamic ids and
names. Tagname is not a useful location strategy to locate elements as there will be many
elements with the same tagname. LinkText is only useful for the anchor <a> tags only. Also, it is
not useful when the visible text changes as in multilingual systems
It is noted that most of the amateur Selenium automation engineers do not pay much attention
to master location strategies. Recording and playback will not work with the applications with
dynamic elements. This leads to failure of the automated test scripts (brittle) when web pages
with dynamic contents are automated. Most of the testers rely on extracting the XPaths from
browser plugins. These tools have limitations and do not provide the best XPath for dynamic
elements.
We will discuss XPath in detail with examples and explore a few tools to generate XPaths easily.
We write following two equations. A=B and B=C. We ask the students what can be derived from
these two expressions. Immediately students reply with the answer A=C, even before the
question is asked :-).
•
o XPath can be used for locating the elements in XML
o XML and HTML have similar syntax (HTML is a subset of XML)
Hence we can derive XPath can be used for locating elements in HTML pages (web pages)
too . Selenium uses XPath to locate elements in web pages.
•
o Locating elements with respect to a known element
o Locating elements with partially static attribute values
o Locating elements without attributes or without unique attributes
Types of XPath
We have grouped XPaths into 2 types.
Absolute XPath
Absolute XPaths starts with the root of the HTML pages.
Absolute XPaths are not advisable for most of the time due to following reasons
1. Absolute XPaths are lengthier and hence they are not readable
2. Absolute XPaths are not resilient. They tend to break when minor structural changes
are introduced to the web pages
Absolute XPaths shall be used only when a relative XPath cannot be constructed. (highly
unlikely). It is not recommended to use absolute XPath in Selenium.
Example: /html/body/div[1]/div/div[2]/form/div[2]/input
Relative XPath
Relative XPaths is used for locating elements with respect to a element with known
(solid) XPath. The element of your choice is referred relative to a known element.
Syntax: Relative XPaths are started with two forward slashes ‘//’.
Examples :
1. //div[@id=’divUsername’]/input
2. //form/div[@id=’divUsername’]/input
3. //form/*/input
There could be zero or more elements between the context element (starting element with a
known Xpath) and the target element
NOTES:
• Unique
• Descriptive
• Resilient
• Shorter in length
When you want to locate a single element your XPath should have only one candidate element
(unique). It will be easier to identify the element if it is descriptive and
short(for maintainability). XPaths generated from tools may not be user-friendly. It should
be possible to locate an element with given XPath when the test is run again in subsequent
releases too. XPath should be selected in such a way it is valid even after changes in DOM
(resilient). You will have multiple XPath options. A shorter XPath shall be selected to make it
more readable in your test scripts.
Syntax:
//*[@attributeName=’value’]
Let’s locate the username field in following.
We have three valid XPaths
Examples :
1. //*[@id=’txtUsername’]
2. //*[@name=’txtUsername’]
3. //*[@type=’text’]
NOTE: Third XPath should not be used even though it is a valid XPath. Because It will not be a
unique XPath in most of the cases. There will be many elements with type=’text’. Hence
Selenium will not be able to locate the target element uniquely.
Single quotations should be used to enclose the values (in Java).You need to use escape
character if you wish to enclose the values with double quotes.
Example : //*[@id=\”txtUsername\”]
In our real life we cannot locate a person with name Mohammed in a Muslim community.
Examples :
Examples :
1. //input[@id=’txtUsername’]
2. //input[@name=’txtUsername’]
This is one of the most commonly used Xpath. Most of the plugs can generate above XPaths
automatically
Syntax:
//tagName[text()=’exact text’] or
/*[text()=’exact text’]
Let’s consider locating following hyperlink
Examples :
1. //a[text()=’Pragmatic’]
2. //*[text()=’Pragmatic’]
//tagName[contains(text(),’substring’)]
//tagName[contains(.,’substring’)]
//*[contains(text(),’substring’)]
Examples :
1. //a[contains(text(),’Pragmatic’)]
2. //a[contains(., ‘Test Labs‘)]
3. //*[contains(text(), ‘Test Labs‘)]
Validate the XPath syntax before running the test scripts. Validating the XPath is discussed in a
separate section.
Syntax :
Examples :
1. //a[starts-with(text(),’Pragmatic’)]
2. //*[starts-with(text(), ‘Prag‘)]
Syntax :
1. //tagName[@value=’visibleText’]
Examples :
1. //input[@value=’Janesh’]
We have already discuss the process of locating elements by tag-name and an attribute.
Similar technique is used in Selenium for locating elements when there are more than one
elements with a given attribute. We will use two or more attributes together to locate an
element uniquely.
Syntax :
//*[attribute1=’value1’][attribute2=’value2’]…[attributeN=’valueN’] or
//tagName[attribute1=’value1’][attribute2=’value2’]…[attributeN=’valueN’] or
//*[attribute1=’value1’ and attribute2=’value2]
//tagName[attribute1=’value1’ and attribute2=’value2]
Examples :
1. //*[@type=’submit’][@value=’LOGIN’]
2. //input[@class=’button’][@type=’submit’][@value=’LOGIN’][@name=’Submit’
3. //*[@type=’submit’ and @value=’LOGIN’]
Locating Elements with Dynamic Attribute values
Following syntax could be used when a part of the attribute’s values are NOT changed. We can
use the non changing value for locating the element.
Syntax :
Examples :
1. //a[contains(@href,’pragmatic’)]
2. //*[contains(@href,’testlabs’)]
3. //a[starts-with(@href,’pragmatic’)]
The ends-with() function is part of XPath 2.0. Most of the browsers do not support Xpath 2.0 at
the time of the writing.
We do this very well in our real life. We always give direction to an unknown location with
respective to a well known location (a landmark). Giving direction to your home from a well-
known shop, statue, railway station etc.
XPath has thirteen (13) different axes. We will look into a subset of useful axes in this blog post
which can be used with Selenium.
Your target element should be closer to the known element (context element) to make XPath
shorter, resilient and readable.
Locating a parent element
The parent axis contains the parent of the context node. Every context element has only one
parent element except root element (html).
Syntax :
//<knownXpath>/parent::* or
//<knownXpath>/parent::elementName
//<knownXpath>/..
Let’s see how to locate the form element with respect to the username field. We need to select
an element with unchanging XPath. In this case we will take the username field.
Examples :
1. //input[@id=’txtUsername’]/parent::form
2. //input[@id=’txtUsername’]/parent::*
3. //input[@id=’txtUsername’]/..
There can be only one parent to a context (known) element. Hence specifying the element
name is optional. But it is good to specify the element name for readability.
Syntax :
//<xpathOfContextElement>/child::<elementName> or
//<xpathOfContextElement>/child::*
//<xpathOfContextElement>/<elementName>
Examples :
1. //div[@id=’divUsername’]/child::input
2. //div[@id=’divUsername’]/input
//<xpathOfContextElement>/*/<elementName>
//<xpathOfContextElement>/child/<elementName>
Examples :
1. //form/*/input
2. //form/div/input
Syntax :
//<xpathOfContextElement>/ancestor::<elementName> or //<xpathOfConte
xtElement>/ancestor::*
Examples :
Syntax :
//<xpathOfContextElement>/descendant::<elementName> or //<xpathOfCon
textElement>/descendant::*
Examples :
1. //form[@id=’frmLogin’]/descendant::input
2. //form[@id=’frmLogin’]//input
Syntax :
//<xpathOfContextElement>/following::<elementName> or
//<xpathOfConextElement>/following::*
Examples :
1. //input[@id=’txtUsername’]/following::input
2. //input[@id=’txtUsername’]/following::*
There are two candidate elements. Any descendant elements after the first candidate in the
path are excluded by Selenium when you use findElement method.
To select the login button input element with respect to the username field.
1. //input[@id=’txtUsername’]/following::input[last()]
2. //input[@id=’txtUsername’]/following::input[2]
The preceding axis contains all nodes that are descendants of the root of the tree in which the
context node is found, are not ancestors of the context node, and occur before the context
node in document order
Syntax :
//<xpathOfContextElement>/preceding::<elementName> or
//<xpathOfContextElement>/preceding::*
Examples :
1. //span[text()=’Password’]/preceding::input
There will be two candidate elements (username and password elements). Selenium will select
the password input element when findElement method is used. Elements are ordered from the
context element (span).
2. //span[text()=’Password’]/preceding::input[2]
Syntax :
//<xpathOfContextElement>/following-sibling::<elementName> or
//<xpathOfContextElement>/following-sibling::*
Examples :
1. //*[@id=’txtUsername’]/following-sibling::span
2. //*[@id=’txtUsername’]/following-sibling::*
Locating preceding sibling
Keyword preceding-sibling:: is used to selects the sibling(s) that comes before the context
node with a known XPath, those elements (children) of the context node’s parent that occur
before the context element in document order.
Syntax :
//<xpathOfKnownElement>/preceding-sibling::<elementName> or
//<xpathOfKnownElement>/preceding-sibling::*
Examples :
1. //span[contains(text(),’Username’)]/preceding-sibling::input
2. //span[contains(text(),’Username’)]/preceding-sibling::*
With this we complete discussion of XPath with axes. Please note that we have not discussed
attribute, ancestor-or-self, descendant-or-self, namespace and self axes in this article as they
do not have practical usage in the context of Selenium.
Syntax :
XPath1|Xpath2….|XPathN
If the first XPath is available in the first element is selected by Selenium for further actions. If
both are available first one is Selected when you use findElement method. Both will be selected
if you use findElements method. If only second XPath (Xpath2) is available then second
element will be selected. If both of them are NOT available Selenium gives an
error, NoSuchElementException when you use findElement method.
Example :
1. //input[@id=’txtUsername’]|//input[@name=’txtPassword’]
In this example available elements can be located.
This is useful when you know one of them would exist when the page is loaded.
2. //*[@id=’txtUsername’]|//*[@name=’txtPassword’]|*[@name=’btnLogin’]
Say you need to locate element(s) with deal price greater than 100
You can combine the techniques learned to build complex XPaths and locate any element in
DOM.