When working in web development and web testing, it can be necessary to traverse an HTML document and identify specific elements on a web page. One case in which this is particularly useful is in the development of automated UI tests. Oftentimes, automating web application testing is dependent upon programmatically locating elements on a web page and leveraging these elements to perform specific actions.
In this blog post, we examine a strategy for locating elements known as XPath. We also discuss the following topics:
Overview – What is XPath?
The Basics – XPath syntax and the difference between absolute and relative XPath
XPath functionality
XML Path Language, known as XPath, is a language that enables the pinpointed querying of elements in an XML document. As HTML documents are similar in nature to XML documents (being composed of tags and attributes and organized in a hierarchical, tree-like manner), XPath serves as a flexible tool for traversing the DOM of these documents as well.
Before examining XPath syntax in detail, let’s first analyze one core feature that exemplifies XPath’s flexibility – the ability to query for an element in both absolute and relative fashion.
XPath's expressions can be written to locate elements using both absolute and relative pathing. But what does this mean?
An absolute XPath for an element contains the complete path to said element from the root of the document. This type of path expression begins with the root element of the document or a single forward slash indicating that the path starts at the root of the document. Furthermore, a single forward slash divides each element in the path expression, indicating a direct path to the element.
A relative XPath for an element, on the other hand, allows you to begin the path to said element from anywhere in the document. When using relative XPath, the expression begins with two forward slashes. This indicates that the path to the desired element need not begin at the root of the document.
Given the reality that web pages are modified fairly frequently, it often makes more sense to leverage an element’s relative XPath rather than its absolute XPath. This prevents changes elsewhere in the document from potentially breaking the expression. Let’s imagine, for instance, that we have the following HTML, and we want to locate the input element with the id attribute value of “search-field” using XPath:
<html>
<body>
<form>
<div>
<input id=“other-field”></input>
</div>
<div>
<input id=“search-field”></input>
</div>
…
</form>
</body>
</html>
Considering the above sample HTML, an example of an absolute XPath for the input element with an id value of “search-field” would be as follows:
/html/body/form/div[2]/input
Take note of the single forward slash, indicating that this expression starts at the root of the document. Due to the use of the single forward slash at each element, each tag drilling down to the input element must be included in the path.
Furthermore, take note of the div portion of the expression:
div[2]
The value [2] represents a predicate in the expression. This indicates navigation to the second div element within the body element. Within the second div, we locate the input element.
Now, let’s imagine that the HTML was modified to read as follows:
<html>
<body>
<form>
<div>
<input id=“other-field”></input>
</div>
<div> … </div>
<div>
<input id=“search-field”></input>
</div>
…
</form>
</body>
</html>
The input element with an id value of “search-field” was not touched as part of this modification, but the above absolute XPath expression for the aforementioned input element is no longer valid following the addition of another div element above the div that holds this input element. After this change, the proper absolute XPath for this input element is as follows:
/html/body/form/div[3]/input
Therefore, if using XPath to locate this element as part of a test script, the expression would need to be updated following this unrelated HTML change in order for the test case to succeed again. However, an alternative way to avoid this scenario would be to use a relative XPath expression for the input element:
//input[@id=‘search-field’]
Here, the expression begins with two forward slashes to indicate that the path need not begin at the root of the document. The expression queries for an input element with an id attribute value of “search-field.” This expression will succeed in locating the input element as long as the input element itself is not modified in a way that invalidates the expression.
The examples above should give you a basic understanding of valid syntax when using XPath, while also illustrating the difference between absolute and relative as it relates to XPath. Now, let’s take a look at a quick breakdown of the components used to construct an XPath expression for selecting an element on a page, given the basic functionality discussed above.
/ or // | Indicating navigation via absolute ( / ) or relative ( // ) path |
Element type | The element type (tag name) being selected as part of the path expression (i.e. div, select, input, etc.) |
Predicate | Encapsulated by square brackets and used to identify an element based on provided conditions. One manner in which a predicate can be used is to impose a condition on a particular attribute value. In this case, the attribute name is preceded by the @ character, as shown here: [@id=‘search-field’] |
The above components are then leveraged to construct an expression that drills down to the element the developer wishes to locate. See the following example showing the basic structure:
/ Element_1 [Predicate] // Element_2 [Predicate]
While the above does not delve into all the intricacies of XPath syntax, it should give you a basic understanding and enable you to get started building expressions.
With all of the above in mind, let’s discuss some additional functionality available to a developer when using XPath.
XPath functions, operators, and axes provide functionality to simplify the effort involved in certain operations. Below are a few of the popular ones we’d like to highlight:
The following is an example of an XPath function:
contains() – The contains function in XPath works similarly to that in other languages. For instance, the contains function can be used to locate an element when an attribute on the element has a value that contains a particular substring:
//div[contains(@class,‘sample-class’)]
The above expression can be used to locate div elements with a class attribute that includes the substring “sample-class” anywhere in the HTML document.
The following are examples of XPath operators:
and – The and operator can be used to locate elements based on the evaluation of multiple conditions. See the following expression:
//div[@id=‘container’ and @name=‘container-name’]
In this example, the div element will only be returned if both the id and name attributes match the provided values.
or – Like the and operator, the or operator in XPath can also be used to locate elements based on the evaluation of multiple conditions. Consider the following example:
//div[@id=‘container’ or @id=‘other-container’]
Here, the div element will be returned if the id attribute value is either “container” or “other-container.”
The following are examples of XPath axes. These allow us to select elements based on their relationship to the currently selected element or elements given the XPath expression when the axis is invoked.
parent – In the case of parent, this means selecting the parent elements of the context elements (those currently selected by the XPath expression). Consider the following:
/
/div[@id=‘container’]/parent::*
This expression selects the parent element to the div with the id attribute value “container” (regardless of the tag name).
child – The child axis is used to locate all children of the context elements:
//div[@id=‘container’]/child::*
This expression selects the child elements for the div with the id attribute value “container” (regardless of the tag name).
Let’s take a look at one more example:
//div[@id=‘container’]/child::input
This expression selects all input elements that are children of the div with the id attribute value “container.”
Selenium is a highly utilized open-source framework for automating browser actions in an effort to provide thorough testing of web applications. XPath can be used in conjunction with Selenium to enable efficient element location in web application test scripts.
As discussed above, XPath enables you to locate elements on a web page. When used with Selenium, XPath can assist in locating elements that can then be leveraged to perform actions to test functionality. This could mean testing search functionality by using XPath expressions to locate the search field and submit button. Or, it could mean testing new user registration by using XPath expressions to locate the required form fields in which a new user must enter data, then using another XPath expression to locate the submit button to execute the registration process.
In this way, XPath helps traverse HTML documents and locate the elements necessary to automate tests for critical web application functionality.