WebDriver Tutorial 2 : Locating Elements and Mastering XPath
In this tutorial, we will look deep into the various methods of finding the right locators and on how to find xpath for elements in DOM.
A bit about HTML tags
Anyone who is working on WebDriver should have a strong understanding on HTML tags and attributes. We will be more focusing on the attributes which helps us to identify the elements.
These are the common element attributes
- ID is unique in a webpage and therefore has the first preference to locate elements. This is the fastest as well
- Though its not mandatory for name attribute to be unique in webpages, it usually is and can be used if present.
- Class is basically used for styling and other things and therefore several elements usually share a class. So class should be avoided while locating elements
- Note that there can be webpages where these attributes are not available for all elements. There we go for xpath
Locating elements in WebDriver
Elements are located using findElement and findElements methods of WebDriver class. findElement is used to get a single element and findElements provides a list of WebElements.
Both these methods take a By object which has a set of static methods for each attribute used to find the element. We will look into the various methods using the below example
Consider the below html code for an element.
<input id="username_id" name="username" class="inputClass" />
<a href="http://axatrikx.com/" class="urlClass">Some Link Text</a>
- By.className(“inputClass”) for input field
- By.className(“urlClass”) for link
- By.id(“username_id” for input field
- By.name(“username”) for input field
- By.linkText(“Some Link Text”) for link
- By.partialLinkText – Only a part of the link text needs to be provided
- By.partialLinkText(“Some Link”) for link
- By.tagName(“input”) for input field
- By.tagName(“a”) for link
- By.xpath : We have to provide the XPath which we will discuss later in this tutorial
- By.cssSelector : Css Selector is similar to xpath but written in a different format. We will have another tutorial to cover this.
Now we come to the big topic.
Xpath expression is used to locate a particular element (or elements) in a DOM structure. In simple words, its an expression which helps to locate an element in a DOM structure. The first concept we need to focus on is absolute and relative xpath.
Consider this html page
<p>Some text here</p>
<input type="text" />
<p>Some other text here</p>
Now, our aim is to locate the input element which is not straightforward as it doesn’t have any id or name attributes.
Finding the absolute xpath is simple. Navigate from the root element to the element in question. In this case the navigation step is
html > body > first div > second div inside it > input element.
Now convert this to xpath expression.
Two points to note:
- For absolute xpath, the starting element is the root forward by slash (/) here ‘/html’
- If more than one child is present for an element (as in two child divs in line 3 and 11 for parent element body(2)), then the index should be provided (nth child should be given as div[n]).
Follow this approach to find the relative xpath for that element.
- If the element doesn’t have any unique locators, check if its parent (in this case, the div in line no 7) has any attributes.
- If not, check its parent and so on till you find an ancestor who has any unique attributes
- Once you find an ancestor, follow the same approach for absolute path to construct the xpath expression.
BUT, since we are not starting from the root element, we use double slash (//) before our first element (the ancestor which has an attribute).
Here we start from our element and since it doesn’t have an id, we check its parent (line 7) and see that it doesn’t have any attributes. We check its parent in line 3 and find that it has an id of ‘mainDiv’. So we stop and try to construct the xpath.
Div with id of mainDiv > second child div > input
Changing it to xpath expression :
Points to note:
- Since we are not starting from the root, our starting node should be unambiguous. That is the reason we look for a unique attribute (such as id), so that there will be only one element with that attribute and therefore can be found out.
- Note the way the first div was given. The same pattern can be used for any attribute. For eg, if the div had a name, the expression would be //div[@name=’nameOfDiv’]/div/input
- The remaining nodes are put together in the same way as in absolute path.
Few other syntaxes:
.. represents parent node. In above html //div[@id=’anotherDiv’] presents the div at line 11, and //div[@id=’anotherDiv’]/.. represents its parent body. So //div[@id=’anotherDiv’]/../div represents div at line 3 and //div[@id=’anotherDiv’]/../div presents itself (line 11)
For finding an element with its text content, we can use text() method. For eg: We can find the ‘p’ tag with text content of “Some text here” using the expression
This is similar to text(), but we don’t need to know the entire text content. The below line will find the p tag from line 13
The dot as the first attribute for contains represents the text(). We can use it for attributes as well. For eg, the below line locates the div at line 3
Parent node can be found out using this expression as well. Below expression gets the parent div. Note that <node> should be replaced with the tag of the parent
Similarly other tags such as child::<node>, descendant::<node>, preceding-sibling::<node> and following-sibling::<node> are also present and are often useful.
Next Topic: Mastering WebDriver API