You are on page 1of 15

Introduction to XPATH

Selenium test automation engineers must be very comfortable in locating elements in web
pages. XPath and CSS are very powerful location strategies used in Selenium as compared to
other location strategies (id, name, link, partialLinkText, tagName etc) .

Mastering XPath or CSS is essential for the Selenium test automation engineers to locate
dynamic web elements.

It is noted that new Selenium automation engineers do not pay much attention to master
location strategies. This leads to failure of test automation efforts when web pages with dynamic
contents are automated.

Most of the testers rely on extracting the XPaths from Firebug/Firepath like tools. The tools
cannot be used directly for dynamic web elements.

We will discuss XPath in detail with examples.

We have created similar document for CSS too

XPath for locating Web Elements

I have my own way of introducing (explaining) XPath to the trainees in my training sessions.

When A=B and B=C. I ask the students what can be derived from these expressions.
Immediately they reply with A=C.

Then I give following two statements


1. XPath is used for locating the elements in XML documents
2. XML and HTML has similar syntax (HTML is an XML file)

Hence XPath can be used for locating elements in HTML pages/web pages.

Why do we need to master many XPath syntaxes?


We may not be able to locate the elements directly using their unique attributes as some
element do not have unique attributes. Some attributes are dynamically changed.

Hence we may have to locate them differently than the static elements.
Locate elements with respective a known element
Locate elements with partial fixed attribute values
Locate element without attributes or without unique attributes
XPath can do bidirectional navigation (Going forward and backward)
XPath is one of most flexible and strongest location strategy

Types of XPath

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
Absolute XPaths are lengthier and not readable
Absolute XPaths are brittle when minor structural changes are done to the web pages

Absolute XPaths shall be used only when a relative a XPath cannot be constructed. (highly
unlikely). Absolute XPaths tends to break as web pages/content is changed. Hence it not
recommended to use absolute XPath in Selenium.

Most of the beginners tend use absolute XPaths when they copy them from tools like
FireBug. These XPaths are tend to break (brittle) most of the time.

Syntax: Absolute XPaths start with /html

Example : /html/body/div[1]/div/div[2]/form/div[2]/input

Relative XPath
Relative XPaths is used for locating an element from a known element. The element of your
choice is referred relative to a known element.

Syntax : Relative XPaths are started with two forward slashes. //

Example : //div[@id='divUsername']/input

Absolute XPaths are faster than the relative XPaths

IF there are multiple elements for an XPath?


Selenium will select the first element in the path if there are multiple candidates for a given
XPath. If you want to specify the location of the element square brackets with the sequence
number shall be used.

Examples :
To select the third input element : //form/input[3]
To select the last input element : //form/input[last()]

Locating elements by position is discussed further in a separate section


What should be considered when choosing a XPath?
It is important to consider following while choosing a XPath from available options.
A good locator is,

Unique
Descriptive
Unlikely to change

Sample HTML
Following simple HTML is used in most of the CSS examples in this document

<html><body>
<form id=login>
<input name=txtUserName id=txtUsername type=text class=userName >
<input name=txtPassword id=txtPassword type=password class=password >
<input name=submit id=btnLogin type=submit class=button>
</form>
</body></html>

Locating Elements with Known Attributes


Following syntax can be used for locating elements when at least one attributes are unique and
static (not changed).

//*[@attributeName=value]

Let's consider the username field

<input id="txtUsername" type="text" name="txtUsername">

Examples :
1. //*[@id='txtUsername']
2. //*[@name='txtUsername']
3. //*[@type='text']

Third XPath is not used even though it is a valid XPath. BUT It is not unique. There might
be many elements with attribute type=text.

Locating Elements with known Element and Attributes

//elementName[@attributeName=value]
Let's consider the username element again

<input id="txtUsername" type="text" name="txtUsername">

Examples :
1. //input[@id='txtUsername']
2. //input[@name='txtUsername']
3. //input[@type='text']

Third option is valid but it is not unique. Hence it is discouraged to use in test scripts. There
could be many elements with type=text.

Locating Elements with Known Visible Text (exact match)


Following syntax is used for locating elements containing some text

//elementName[text()=exact text] or
//*[text()=exact text]

<a target="_blank" href="http://www.pragmatictestlabs.com">Pragmatic</a>

Examples :
//a[text()='Pragmatic']
//*[text()='Pragmatic']

The text is case sensitive.

Warning : Locating by the visible text is not advisable if you are testing a multilingual application
and same text is appearing in more than one location.

Locating Elements when part of the visible text is known (partial match)

//elementName[contains(text(),part of the text)]


//elementName[contains(.,part of the text)]
or
//*[contains(text(),part of the text)]

<a target="_blank" href="http://www.orangehrm.com">OrangeHRM, Inc</a>

Examples :
//a[contains(text(),'Orange')]
//a[contains(.,'Orange')]
//*[contains(text(),'Orange')]
Ensure closing brackets are available.

Locating elements when starting text is known

//elementName[starts-with(text(),starting text)] ,

Example :
//a[starts-with(text(),'Orange')]

Locating Elements with Dynamic Attributes


Following syntax could be used when a part of the attribute values are NOT changed. We can
use the non-changing value for locating the element.

//elementName[contains(@attributeName,part of the value)]

Example:
//a[contains(@href,'orangehrm.com')]

You can use //elementName[starts-with(@attributeName,part of the value)]

And //*[contains(@attributeName,part of the value)] too

The ends-with function is part of xpath 2.0. Browsers generally only support 1.0 at the time
of this writing. Hence ends-with is not included.

Locating Elements with Attributes

//*[@attributeName=value]

Example:
//*[@id='txtUsername']

Locating Elements with Multiple Attributes


Sometimes it may not be possible to locate an element with a single attribute. In real world we
have similar issue. We cannot locate a person with just first name or last name. We will have to
use combination of first name and last name to locate a person without any confusions.

//*[attribute1=value1][attribute2=value2]...[attributeN=valueN]

Example :
//*[@id='txtUsername'][@name='txtUsername']

You can include the element name too

//elementName[attribute1=value1][attribute2=value2]...[attributeN=valueN]

Example :
//input[@class='button'][@type='submit'][@value='LOGIN'][@name='Submit']

Locating elements relative to known element


If an element of our interest do not have a unique attribute(s)/locator, we need to locate the
element with respective to a known element.

We do this very well in our real life. We always give direction to a new location with respective
an already known location (a landmark). Giving direction to your home from a well know shop,
statue, railway station etc.

XPath has thirteen (13) different axes. We will look into a subset of useful axes in this
document.

Figure: XPath Axes


Source: XPath Expression components.
http://www.iro.umontreal.ca/~lapalme/ForestInsteadOfTheTrees/HTML/ch04s01.html

XPath Axis name Description

ancestor Parent of a known element , its parents

descendants Children of a known element, its children

following Elements after the known element

following-sibling Sibling elements after the known element

parent Parent element of the known element

preceding Element before the known element

preceding-sibling Sibling elements before the known element

When using those axis notations make sure to have a good understanding on the DOM
structure of your web page

Locating a parent element

The parent axis contains the parent of the context node.

//<knownXpath>/parent::* or
//<knownXpath>/parent::elementName
XPath of the known element : //div[@id='divUsername']

Now we can locate the parent form element with respect to the div element

//div[@id='divUsername']/parent::form

Also
//div[@id='divUsername']/parent::*

This can be written as //div[@id='divUsername']/.. also

There can be only one parent to a context (known) element. Hence specifying the element
name is optional.

Locating a child element

The child axis contains the children of the context node

//<xpathOfKnownElement>/child::<elementName> or
//<xpathOfKnownElement>/child::*
Xpath of the known element //div[@id=divUsername]
Xpath to the child element is //div[@id='divUsername']/child::span

You can use / instead of child:: from the XPath. //div[@id='divUsername']/span

Locating ancestors of a known element


The ancestor axis contains the ancestors of the known element ; ancestor axis consist of the
parent of known element and the parent's parent so on..

//<xpathOfKnownElement>/ancestor::<elementName>
or //<xpathOfKnownElement>/ancestor::*

Examples :
//input[@id='txtUsername']/ancestor::form
//input[@id=txtUsername]/ancestor::*

Where there are multiple elements first will be selected by Selenium.


Locating following elements
Keyword following can be used for locating an element anywhere below the tree with respect
to the known element.

//<xpathOfKnownElement>/following::<elementName>
or //<xpathOfKnownElement>/following::*

//input[@id='txtUsername']/following::input

Any descendant elements are excluded

Locating preceding element


Keyword preceding is used for locating an element above the tree with respect to a known
(xpath) element.

//<xpathOfKnownElement>/preceding::<elementName>
or //<xpathOfKnownElement>/preceding::*

Example :
//*[@id='txtPassword']/preceding::div[1]

Any ancestors are excluded

Locating following sibling


Following could be used to locate the following sibling elements with respective to a known
element.

: //<xpathOfKnownElement>/following-sibling::<elementName> or
//<xpathOfKnownElement>/following-sibling::*

Example :
//*[@id='txtUsername']/following-sibling::span

Locating preceding sibling

//<xpathOfKnownElement>/preceding-sibling::<elementName> or
//<xpathOfKnownElement>/preceding-sibling::*

Example :
//span[contains(text(),'Username')]/preceding-sibling::input

Locating Optional XPaths


You may know possible (options) XPaths in advance but not sure which one will be
available/correct at the time of the testing. Possible XPaths shall be separated by | character.

XPath1|Xpath2

If the first xpath is available first element is selected by Selenium for further actions. If both are
available first one is Selected.

Dont keep spaces between the pipe character and the XPaths.

Locating an element by position


This can be used for locating an element explicitly when there are many elements matching the
XPath.

Xpath[position] , Xpath[last()] , Xpath[last()-n] and


Examples :
//div[@id='branding']/a[2]
//form/input[last()]
//form/input[last()-1]

For selecting an element before a given element


//form/input[position()<3 ] selects first 2 input elements

Validating XPath
It is important to ensure XPath used in your automation script is valid before running the script.
There are number of tools available to validate the correctness of the XPaths.

Verify using FirePath


Install Firebug on your Firefox browser. Then install FirePath which will appear as an addon to
Firebug.
1. Open context menu on the web page. Select Inspect with Firepath
2. Select XPath from drop down (usually XPath is selected by Default) .
3. Type the XPath
4. Click Eval button to verify the XPath
Verify using FireFinder
You can use FireFinder also to verify the Xpath. Install Firebug on your Firefox browser. Then
install FireFinder on your browser.

1. Open Firebug (using context menu in web page).


2. Select FireFinder tab.
3. Type the XPath
4. Click Filter button to verify the XPath
5. Matching element(s) will be displayed (if available)

Practice XPath
You can use XLab for practicing the XPath
1. Expressions
2. Axis

<<We are looking for developing a XLab site with HTML>>

XPath or CSS
CSS and XPath are the most popular, widely used and powerful location strategies within the
Selenium test automation community.
CSS has gained wider acceptance from the test automation engineers due to following reasons.
(People in favour of CSS says)

CSS more readable ( simpler )


CSS is faster (especially in IE)

Those who are in favour of XPath says about its ability to transverse around the page where
CSS cannot. XPath can traverse up and down the DOM. CSS can traverse only down the DOM.

These claims may be already outdated :-). Some research demonstrate that there is no
significant difference in speed.

Mastering both of them is a good idea for the Selenium test automation engineers who
wish to build their career around Selenium.

It is better to a use single location strategy for a project for number of reasons.

Some gurus advice hybrid approach. They use ID first and and moving to CSS. XPath is
used only when it is required.

Quick Reference

XPath Description

//*[@attribute=value] Locating element with known


attribute.

//element[@attribute=value] Locating element with known


element and attribute.

//element[text()=exact text] Locating Elements with


Known Visible Text (exact
match)

//*[text()=exact text] Locating Elements with


Known Visible Text (exact
match)

/elementName[contains(text(),part of the text)] Locating Elements when part


of the visible text is known
(partial match)
//elementName[contains(.,part of the text)] Locating Elements when part
of the visible text is known
(partial match)

//*[contains(text(),part of the text)] Locating Elements when part


of the visible text is known
(partial match)

//element[starts-with(text(),starting text)] Locating elements when


starting text is known

//elementName[contains(@attributeName,part of the value)]

//*[contains(@attributeName,part of the value)]

//*[attribute1=value1][attribute2=value2]...[attributeN=valueN]

//<knownXpath>/parent::*

//<knownXpath>/parent::elementName

//<xpathOfKnownElement>/ancestor::<elementName>

//<xpathOfKnownElement>/ancestor::*

//<xpathOfKnownElement>/following::<elementName>

//<xpathOfKnownElement>/following::*

//<xpathOfKnownElement>/preceding::<elementName>
//<xpathOfKnownElement>/preceding::*

//<xpathOfKnownElement>/following-sibling::<elementName>
//<xpathOfKnownElement>/following-sibling::*

//<xpathOfKnownElement>/preceding-
sibling::<elementName>
//<xpathOfKnownElement>/preceding-sibling::*

XPath1|Xpath2

Xpath[position] , Xpath[last()] , Xpath[last()-n]

You might also like