Selenium Testing Tools Cookbook(Second Edition)
上QQ阅读APP看书,第一时间看更新

Finding elements using XPath

XPath (the XML path language) is a query language used to select nodes from an XML document. All the major browsers implement DOM Level 3 XPath (using http://www.w3.org/TR/DOM-Level-3-XPath/) specification, which provides access to a DOM tree.

The XPath language is based on a tree representation of the XML document and provides the ability to navigate around the tree and to select nodes using a variety of criteria.

Selenium WebDriver supports XPath to locate elements using XPath expressions, also known as XPath query.

One of the important differences between XPath and CSS is that, with XPath, we can search elements backwards or forwards in the DOM hierarchy, while CSS works only in a forward direction. This means that using XPath we can locate a parent element using a child element and vice versa.

In this recipe, we will explore some basic XPath queries to locate elements, and then examine some advanced XPath queries.

XML documents are treated as trees of nodes. The topmost element of the tree is called the root element. When an HTML document is loaded in DOM, it provides a similar tree of nodes. Here's an example of an HTML page:

<html>
  <head>
    <title>My Book List</title>
  </head>
<body>
  <h1>My Book List</h1>
  <div>
  <table class="main-list">
   <tr>
    <td>Title</td>
    <td>Author</td>
    <td>Publication Year</td>
    <td>Price</td>
    <td>Book Page</td>
   </tr>
   <tr id="book_1">
    <td>XML Developer's Guide</td>
    <td>Gambardella, Matthew</td>
    <td>Publication Year</td>
    <td class="price">44.95</td>
    <td><div class="desc">An in-depth look at creating applications
     with XML.</div></td>
    <td><a href="/book_1.html">
     <img src="/img/book1_png/" alt="XML Developers Guide">
     </a></td>
   </tr>
  </table>
 </div>
</body>
</html>

Let's understand some basic XPath terminology before we move on to using XPath, with the following listed terms. We will use the previous HTML document as an example:

Selecting nodes

XPath uses path expressions to select nodes from the tree. The node is selected by following a path or steps. The most useful path expressions are listed as follows:

How to do it...

Let's explore some basic XPath expressions that can be used in Selenium WebDriver. Selenium WebDriver provides the xpath() method to locate elements using XPaths.

Finding elements with an absolute path

XPath absolute paths refer to the very specific location of the element, considering its complete hierarchy in the DOM. Here is an example where the Username Input field is located using the absolute path. When providing an absolute path, a space is given between the elements:

WebElement userName = driver.findElement(By.xpath("/html/body/div/div/form/input"));

However, this strategy has limitations as it depends on the structure or hierarchy of the elements on a page. If this changes, the locator will fail to get the element.

Finding elements with a relative path

With a relative path, we can locate an element directly irrespective of its location in the DOM. For example, we can locate the Username Input field in the following way, assuming it is the first <input> element in the DOM:

WebElement userName = driver.findElement(By.xpath("//input"));

Finding elements using predicates

A predicate is embedded in square brackets and is used to find out specific node(s) or a node that contains a specific value.

In the previous example, the XPath query will return the first <input> element that it finds in the DOM. There could be multiple elements matching the specified XPath query. If the element is not the first element, we can also locate the element by using its index in the DOM. For example, in our login form, we can locate the Password field, which is the second <input> element on the page, in the following way:

WebElement userName = driver.findElement(By.xpath("//input[2]"));

Finding elements using attributes values with XPath

We can find elements using their attribute values in XPath. In the following example, the Username field is identified using the ID attribute:

WebElement userName = driver.findElement(By.xpath("//input[@id='username']"));

Here is another example where the image is located using the alt attribute:

WebElement previousButton = driver.findElement(By.xpath("//img[@alt='Previous']"));

You might come across situations where one attribute may not be sufficient to locate an element and you need combined additional attributes for a precise match. In the following example, multiple attributes are used to locate the <input> element for the Login button:

WebElement previousButton = driver.findElement(By.xpath("//input[@type='submit'][@value='Login']"));

The same result can be achieved by using XPath and operator:

WebElement previousButton = driver.findElement(By.xpath("//input[@type='submit' and @value='Login']"));

In the following example, either of the attributes is used to locate the elements using XPath or operator:

WebElement previousButton = driver.findElement(By.xpath("//input[@type='submit'or @value='Login']"));

Finding elements using attributes with XPath

This strategy is a bit different from the earlier strategy where we want to find elements based only on the specific attribute defined for them but not attribute values. For example, we want to lookup all the <img> elements that have the alt attribute specified:

List<WebElement> imagesWithAlt = driver.findElements(By.xpath ("//img[@alt]"));

Here's another example where all the <img> elements will be searched and where the alt attribute is not defined. We will use the not function to check the negative condition:

List<WebElement> imagesWithAlt = driver.findElements(By.xpath ("//img[not(@alt)]"));

Performing partial match on attribute values XPath also provides a way to find elements matching partial attribute values using XPath functions. This is very useful to test applications where attribute values are dynamically assigned and change every time a page is requested. For example, ASP.NET applications exhibit this kind of behavior where IDs are generated dynamically.

The following table explains the use of these XPath functions:

Matching any attribute using a value

XPath matches the attribute for all the elements for a specified value and returns the element. For example, in the following XPath query, 'userName' is specified. XPath will check all the elements and their attributes to see if they have this value and return the matching element.

WebElement userName = driver.findElement(By.xpath("//input[@*='username']"));

Here are more examples of using XPath predicates to find elements using their position and contents:

Selecting unknown nodes

Apart from selecting the specific nodes, XPath also provides wildcards to select a group of elements:

Selecting several paths

Using the union | operator in XPath expressions, we can select several paths together, as shown in the following table:

Locating elements with XPath axes

XPath axes help to find elements based on the element's relationship with other elements in a document. The following screenshot shows some examples for some common XPath axes used to find elements from a <table> element. This can be applied to any other element structure from your application.

Locating elements with XPath axes

The following image shows a graphical representation of the HTML elements:

Locating elements with XPath axes

You can find more about XPath axes at http://www.w3schools.com/xpath/xpath_axes.asp.

How it works...

XPath is a powerful language to query and process DOM trees in browsers. XPath is used to navigate through elements and attributes in a DOM tree. XPath provides various rules, functions, operators, and syntax to find the elements.

The majority of browsers support XPath, and Selenium WebDriver provides the ability to find elements using the XPath language.

Using the xpath() method of the By class, we can locate elements using XPath syntax.