Groundbreaking Tips On How To Use XPath In Selenium

Written by Rahul Jain | Published 2020/11/09
Tech Story Tags: xpath | selenium | test-automation | good-company | code-quality | web-development | workflow-automation | productivity

TLDRvia the TL;DR App

Identifying element has always been the trickiest part and therefore require an accurate and correct approach. If you are unable to find elements by the easily available approaches like ID, class, name, link or tagname then XPath in Selenium can help rescue you. Locating dynamic elements have always been the pain area while you wish to automate the scripts, the only ray of hope to deal with such fiascos is XPath. In my current article, I will be digging into the steps of locating an element via XPath example in Selenium and its various ways.

So, What Is XPath In Selenium?

XPath known as the XML path is a language that helps to query the XML documents. It consists of expression for a path along with certain conditions to locate a particular element.
So let’s see how to write an XPath in Selenium. Below is the DOM structure for LambdaTest Registration Page:
<form method="POST" action="https://accounts.lambdatest.com/register">
<input type="hidden" name="_token" value="W4D7bCygQ4abq2Xa3ckZ2rwG3Wk7f9enPXIIPeuF"> 
<div class="col-sm-12 google-sign-form"><p class="signup-titel" style="text-align: center;">SIGN UP FOR FREE</p></div> <div class="col-sm-12 google-sign-form">
<input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 ">
 <input type="text" placeholder="Full Name*" name="name" value="" class="form-control sign-up-input-2 ">
 <input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 "> 
<input type="password" placeholder="Desired Password*" name="password" class="form-control sign-up-input-2 "> <input type="phone" placeholder="Phone*" name="phone" value="" class="form-control sign-up-input-2 "> <p class="terms-cond"><label for="terms_of_service" class="woo">
<input type="checkbox" name="terms_of_service" id="terms_of_service" value="1" class="form-check-input" style="position: relative; margin-left: 0px;"> &nbsp; I agree to the <a target="_blank" href="https://www.lambdatest.com/terms-of-service">Terms
                                    of Service</a>
                                and <a target="_blank" href="https://www.lambdatest.com/privacy">Privacy Policy</a></label></p> <button type="submit" class=" btn sign-up-btn-2 btn-block">Signup for Free</button></div>
 <div class="col-sm-12 link-sect"><p class="login-in-link test-left">Already have an account? <a href="/login">Login</a></p></div></form>
Referenced screenshot of the page:
In order to visualize the above XML document, I have created the below flowchart.
Here, I will write the XPath in Selenium from the root node which is the form tag in our case, then will locate the Full name field using div 2 child and the attribute value of the full name field. The XPath created in this case will be as below:
//form/div[@class=’ col-sm-12 google-sign-form’]/input[@name=’ name’]
In this case, I have referenced one attribute of the children and grandchildren in order to differentiate from the multiple children and grandchildren of each parent. From this we can derive the general syntax of XPath as follows:
//tagname[@attribute name= ‘value’]
Here
  1. // Denotes the current node
  2. Tagname : Define the tagname you are referencing to locate the element.
  3. Attribute Value : The attribute of the define tag through which you wish to narrow down the search.
  4. Value: Represents the value of any chosen attribute.
Nowadays, thorough use of multiple plugins and tools can help one find the XPath in Selenium with relative ease. The reason I don’t encourage people to do so, the XPath provided by these tools sometimes turn out to be brittle. Also, it may lead to people forgetting the basic concepts of creating XPath locators. Using firebug and Chrome Dev Tools one can also copy the required XPath in Selenium.

Types Of XPath In Selenium

There are two types of XPath
  1. Absolute XPath
  2. Relative XPath

Absolute XPath Example In Selenium

In case of absolute XPath in Selenium, the XPath expression is created using the selection from the root node. It starts with a single slash ‘/’ and traverses from the root to the whole DOM to reach to the desired element. The biggest disadvantage of using this as locating an element is, if during the course of development any changes made in the path, may lead to a failed XPath expression. For example:
/html/body/div[1]/section/div/div[2]/div/form/div[2]/input[3]
In the above XPath example in Selenium, if any tag name like section or one of the div’s changes the whole XPath would become invalid leading to script failure.

Relative XPath Example In Selenium

In case of relative XPath in Selenium, the XPath expression is generated from the middle of the DOM structure. It is represented by a double slash ‘//’ denoting the current node. In this case the search will start from the mentioned tagname and string value. It is more compact, easy to use and less prone to been broken. For example:
//input[@name=’email’]
In above XPath example in Selenium, we are searching from the current node with tagname input having attribute as name with value as email.
Below is a code snippet highlighting the XPath written using relative XPath for the register page of LambdaTest.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class RelativeXpathExample {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", " path to chromedriver ");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://accounts.lambdatest.com/register");
        //Relative xpath for organization field
        driver.findElement(By.xpath("//input[@name='organization_name']")).sendKeys("Lambdatest Org");
        //Relative xpath for full name field
        driver.findElement(By.xpath("//input[@name='name']")).sendKeys("Sadhvi Singh");
        driver.close();
        
    }

}

Writing Complex & Dynamic XPath In Selenium Through Various Methods

Using Basic XPath
This is the common and syntactical approach of writing the XPath in Selenium which is the combination of a tagname and attribute value. Here are few basic XPath examples in Selenium:
  • Xpath=//input [@name=’password’]
  • Xpath=//a [@href= ‘https://www.lambdatest.com/’]
  • Xpath=//*[@id=’email_01’]
  • Xpath=//input[name=’email’][@placeholder=’Work Email’]
The first two examples in the basic XPath list seem self-explanatory. In it we have used tags as input and anchor tags with their corresponding attribute value. The last two examples are just extended versions of using XPath in Selenium. In the third example we have just excluded the HTML tag and represented it with an asterisk(*). In this case, the script will search in the DOM with any HTML tag having an ID attribute with value as ‘email_01’. In case of example 4, we have created the XPath using multiple attributes for the single HTML tag.

Using ‘OR’ & ‘AND’

As mentioned these logical expressions are used on the attributes condition. In case of OR any one of the conditions should be true or both, whereas in the case of AND, both the conditions should be fulfilled. For example, for the below DOM structure, XPath using AND and OR can be written as:
< input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 " >
  • Xpath= //input[@type= ‘email’ or @name= ‘email’]
  • Xpath= //input[@type= ‘email’ and @name= ‘email’]
In case of OR if any of the attribute values matches, the element will be located, whereas in case of AND both the attribute values should match and meet, then only the element will be located. The above defined ways have been inculcated in the code snippet below, where we are trying to input values on the register page.
import java.util.concurrent.TimeUnit;
 
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
 
public class XpathExampleWithAndOR {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        
        System.setProperty("webdriver.chrome.driver", " path to chromedriver ");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://accounts.lambdatest.com/register");
        
        //Finding the organization field via xpath using OR
        driver.findElement(By.xpath("//input[@name='organization_name' or @placeholder='Organization/Company Name']")).sendKeys("Lambdatest");
        
        //Finding the full name field via xpath using AND
        driver.findElement(By.xpath("//input[@name='name' and @placeholder='Full Name*']")).sendKeys("Lambdatest");
        
        //Finding the work email field via xpath using OR, where only one of the attribute defined is correct whereas the other incorrect and does not match, still this should work as one of them meets the condition.
        driver.findElement(By.xpath("//input[@name='email' or @id='not present']")).sendKeys("Lambdatest");
        
        //Finding the password field via xpath using AND, where only one of the attribute defined is correct whereas the other incorrect and does not match,this should NOT work as one of them does not meets the condition.
        driver.findElement(By.xpath("//input[@name='password' and @id='not present']")).sendKeys("Lambdatest");
 
    }
 
}
Below is the console error showcasing as the last element not found as conditions were not met.
Please Note: Both ‘and’ and ‘or’ should be case sensitive. In case you tend to use, ‘OR’ or ‘AND’, you will get an error in console stating invalid xpath expression

Using Contains()

This approach in creating XPath in Selenium comes handy when we have part of attribute values that changes dynamically. For example lets say the ID for the login field which is for instance email_01, have the ending number which keeps changing every time the page is loaded. In this case using contains helps us locate element with constant names like in this case ‘email’. Example for creating XPath with contains for the below DOM structure is:
<input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 ">
  • Xpath=//*[contains (@placeholder, ‘Organization)]
  • Xpath= //input[contains (@name, ‘organization)]
  • Xpath=//*[contains(@class, ‘sign-up-input)]
Here in the XPath example above for Selenium we have used attributes like placeholder, name etc and consider partial values to identify elements using contains keywords. Referenced below code snippet highlighting the usage of above XPath creation, in this we are clicking on the ‘Start testing’ button on LambdaTest homepage. Referenced screenshot:
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathContainsExample {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path to chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com");
        
        //Finding the element 'Start testing' having text as same, here we will locate element using contains through xpath
        driver.findElement(By.xpath("//a[contains(text(), 'TESTING')]")).click();
        
        driver.close()

    }

}

Using Starts-With()

This is similar to the above contains method, the only difference is the comparison value here starts with an initial string value. This is useful when partly values changes for a given attribute. Like in the above XPath example, the email value changes for the latter values. Here, one can use starts-with approach to identify the element. Below XPath examples for Selenium, highlight the usage of starts-with for the below DOM structure:
<input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 ">
  • Xpath=//input[starts-with(@placeholder, ‘Organization)]
  • Xpath= =//input[starts-with(@name, ‘organization)]
Here, in the example above we have used two attributes with the starts-with Keyword. The script will find for the tag name and matches with the attribute value that starts with ‘Organization’. Referenced code snippet highlighting the usage of Starts-With keyword while locating element via XPath in Selenium. We will use the same example as above, the only difference is, we will locate an element using starts-with.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathStartsWithExample {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path to chromeDriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com");
        
        //Finding the element 'Start testing' having text as same, here we will locate element using contains through xpath
        driver.findElement(By.xpath("//a[starts-with(text(), 'START')]")).click();
        
        driver.close();
    
    }

}

Using Text()

This keyword is used to create expressions for XPath in Selenium when we have a text defined in an HTML tag and we wish to identify element via text. This comes really handy when the other attribute values change dynamically with no substantial part of the attribute value that can be used via Starts-with or Contains. Below is an XPath example in Selenium, highlighting the usage of text for the following DOM structure:
<button type="submit" class=" btn sign-up-btn-2 btn-block">Signup for Free</button>
  • Xpath= //button[text()=’ Signup for Free’]
  • Xpath=//button[contains(text(),’ Signup’ )]
In the above mentioned examples, we have use the text on the button to identify the element. Here two instances of the examples are used, one where the text is exact matched, whereas the other where the text is matched partially using contains keyword. Referenced snippet below highlighting the usage of the text keyword. In this example, we will be clicking on one of the blogs on the LambdaTest blog page.
Referenced screenshot below:
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathWithTextExample {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        
        
        System.setProperty("webdriver.chrome.driver", "path to the chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com/blog");
    
        
        //Finding the blog with text as 'complete guide on TestNG annotations' element
        driver.findElement(By.xpath("//a[text()='Complete Guide On TestNG Annotations For Selenium WebDriver']")).click();
        
        driver.close();
        
        

    }

}

Using Index

This approach comes in use when you wish to specify a given tag name in terms of index value you wish to locate too. For instance, consider a DOM having multiple input tags for each different field value and you wish to input text into the 4th field. In this case you can use the index to switch to the given tag name. For example:
For the given DOM structure, I wish to locate the second input tag field:
<div class="col-sm-12 google-sign-form"><input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 "> <input type="text" placeholder="Full Name*" name="name" value="" class="form-control sign-up-input-2 "> <input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 ">
  • Xpath= //div[@class= ’ col-sm-12 google-sign-form’]/input[2]
In the above example, the locator with ‘Full name’ as a field will be selected. The first input tag will be ignored whereas the other tag will be considered owing to the index mentioned. This type of approach comes in handy when dealing with data in tables. For example, when you have multiple rows, you can reference the desired row using an index. Reference code snippet using an index for a tabular form of data for the registration page of LambdaTest, where through the form class we are navigating to the ‘full name’ field using index.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathWithIndex {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "C:\\Users\\ss251550\\eclipse-workspace_automate\\Automate_Active_MQ_Process\\ChromeDriver\\chromedriver.exe");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://accounts.lambdatest.com/register");
        driver.manage().window().maximize();
        
        //finding the element through index using the reference of the form field containing the fields in it.
        driver.findElement(By.xpath("//div[@class='col-sm-12 google-sign-form']/input[2]")).sendKeys("sadhvi singh");
      
        driver.close();
        

    }

}

Using Chained XPath In Selenium

As the name signifies, we can use multiple XPath expressions and chained them. For example, in the below DOM structure referencing the LambdaTest homepage links:
<ul class="nav navbar-nav navbar-right">
<li><a href="https://www.lambdatest.com/feature">Live</a></li>
<li><a href="https://www.lambdatest.com/selenium-automation">Automation</a></li> <li><a href="https://www.lambdatest.com/blog">Blog</a></li>
 <li><a href="https://www.lambdatest.com/pricing">Pricing</a></li>
  <li><a href="https://www.lambdatest.com/support/">Support</a></li>
  <li class="sign-in"><a href="https://accounts.lambdatest.com/login">Login</a></li>
 <li class="login"><a href="https://accounts.lambdatest.com/register">Free Sign Up</a>
</li>
</ul>
Here, we will try to navigate to the ‘Login link’. The syntax to achieve it is.
  • Xpath=//ul[@class=’nav navbar-nav navbar-right’]//li[@class=’sign-in’]
In the above XPath example in Selenium, I have located the parent class for the link tags and then navigated to the child using chaining for the ‘login’ link. The above example has been achieved using the below code snippet.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingChaining {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path of chromeDriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com/");
        driver.manage().window().maximize();
        
        //locating the 'login' link using xpath chaining and clicking on it.
        driver.findElement(By.xpath("//ul[@class='nav navbar-nav navbar-right']//li[@class='sign-in']")).click();
        
        //Verifying the current URL on which we post clicking on it.
        String currentURL= driver.getCurrentUrl();
        System.out.println(currentURL);
        
        driver.close();

    }

}
Console Output

XPath axes

XPath axes come in handy when the exact element tagname or its attribute value are dynamic and cannot be used to locate an element. In this case locating the element after traversing through the child/sibling or parent will be an easy approach. Some of the widely used XPath axes are:
1. Following: This XPath axis helps to locate elements following the current node. Mentioned below is the DOM structure of the LambdaTest Registration Page.
<div class="col-sm-12 google-sign-form">
                              <input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 "> 
                             <input type="text" placeholder="Full Name*" name="name" value="" class="form-control sign-up-input-2 ">
                            <input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 ">
                           <input type="password" placeholder="Desired Password*" name="password" class="form-control sign-up-input-2 ">
                           <input type="phone" placeholder="Phone*" name="phone" value="" class="form-control sign-up-input-2 "> 
                            <p class="terms-cond">
                          <label for="terms_of_service" class="woo">
                         <input type="checkbox" name="terms_of_service" id="terms_of_service" value="1" class="form-check-input" style="position: relative; margin-left: 0px;"> &nbsp; I agree to the 
                         <a target="_blank" href="https://www.lambdatest.com/terms-of-service">Terms
                                    of Service</a>
                                and 
                      <a target="_blank" href="https://www.lambdatest.com/privacy">Privacy Policy</a>
</label>
</p> 
<button type="submit" class=" btn sign-up-btn-2 btn-block">Signup for Free</button>
</div>
Referenced screenshot highlighting the two input elements, wherein we will try to locate the element ‘Full name’ field through the element ‘Organization’ field
  • Xpath=//input[@name=’ organization_name’]//following::input[1]
  • Xpath= //input[@name=’ organization_name’]//following::input
In the above-mentioned examples, the first one will select the input following the organization element, whereas in the second example, it will select all elements following the organization element having input tag. These are useful when we intend to locate an element in a table or when we do not have any whereabouts of the following element from the current node.
Mentioned below code snippet displays the elements located via following. In this example, we will use the Lambatest homepage, where we will traverse through the menu header options using the single header class. Referenced screenshot below:
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingFollowing {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        System.setProperty("webdriver.chrome.driver", " path of chromedriver ");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com/");
        driver.manage().window().maximize();
        
        //Locate element with the link blog using following axes
        driver.findElement(By.xpath("//ul[@class='nav navbar-nav navbar-right']//following::li[3]")).click();
        
        driver.close();
        
    }

}
2. Following sibling: This is one concept that people tend to get confused with. All you get to clear yourself with this concept, is siblings. In case of following all nodes under the current node are the targeted ones irrespective they are under(children) the context node or not but follows below the context node. In case of following siblings, all following nodes of the context node, that shares the same parent, are applicable. In this case all siblings are referred to as children of the parent node. So if you are referencing one of the children and wish to navigate to other children of the same parent that follows it, following sibling does the business.
For example, using the LambdaTest homepage links, in the DOM structure below, one of the children has been referenced, and from it, we will navigate to its siblings.
<ul class="nav navbar-nav navbar-right">
<li><a href="https://www.lambdatest.com/feature">Live</a></li>
<li><a href="https://www.lambdatest.com/selenium-automation">Automation</a></li> <li><a href="https://www.lambdatest.com/blog">Blog</a></li>
 <li><a href="https://www.lambdatest.com/pricing">Pricing</a></li>
  <li><a href="https://www.lambdatest.com/support/">Support</a></li>
  <li class="sign-in"><a href="https://accounts.lambdatest.com/login">Login</a></li>
 <li class="login"><a href="https://accounts.lambdatest.com/register">Free Sign Up</a>
</li>
</ul>
In this case, the parent is,its children are the different li, here we will locate the sign in link and from their locate the login using following sibling
  • Xpath= //li[@class=’sign-in’]//following-sibling::li
Below is a code snippet incorporating the XPath example in Selenium.
package ChromeDriver;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathWithFollowingSibling {

    public static void main(String[] args) {
        // TODO Auto-generated method stub'
        

        System.setProperty("webdriver.chrome.driver", "path of chromeDriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com/");
        driver.manage().window().maximize();
        
        //locating the 'sign-up' link using xpath following sibling and clicking on it.
        driver.findElement(By.xpath("//li[@class='sign-in']//following-sibling::li")).click();
        
        //Verifying the current URL on which we post clicking on it.
        String currentURL= driver.getCurrentUrl();
        System.out.println(currentURL);
        
        driver.close();


    }

}
Console Output
3. Preceding:This method helps in locating elements before the current node, as in the preceding element from the current node with XPath in Selenium. Below is a demonstration of the DOM structure.
<input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 ">
<input type="text" placeholder="Full Name*" name="name" value="" class="form-control sign-up-input-2 ">
<input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 ">
Referenced screenshot below:
  • Xpath=//input[@name=’password’]//preceding::input[1]
  • Xpath=//input[@name=’password’]//preceding::input
In the above-mentioned example, the first one will locate elements with the field as email whereas the other one will locate all elements before the current node i.e. password field. This is also useful in locating elements that cannot be located by any means and can be traversed through. For example, in the case of cross browser testing, sometimes few elements cannot be recognized on IE browsers, legacy browser versions. In this case traversing to these elements using precedence or following could be helpful. Referenced example below with code snippet, highlighting how using the blog link on the LambdaTest homepage, we will circulate through the Automation tab.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingPreceeding {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path of chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com/");
        driver.manage().window().maximize();
        
        //Fnding the automation link using the blog link
        driver.findElement(By.xpath("//a[text()='Blog']//preceding::li[1]")).click();
        
        driver.close();

    }

}
4. Preceding-Sibling: This is a concept similar to following sibling, the only difference in functionality is that of preceding. So, in this case, you can switch among the siblings, but in this, you will switch from the context node being a child and move to the preceding node, you wish to locate. Both the children will share the same parent. Using the same example as mentioned in the following sibling, we will now move from the sign-up link to the login link using preceding-sibling. The syntax for the same is
  • Xpath= //li[@class=’login’]//preceding-sibling::li[1]
Note: In case you do not specify the index of the sibling you wish to navigate it may choose to select any. For specific selection, you need to mention the index. In case of a single sibling from the context node, you need not specify the index. Below is the code snippet for the same XPath example in Selenium.
package ChromeDriver;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathWithPrecedingSibling {

    public static void main(String[] args) {
        // TODO Auto-generated method stub'
        

        System.setProperty("webdriver.chrome.driver", "path of chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.lambdatest.com/");
        driver.manage().window().maximize();
        
        //locating the 'login' link using xpath preceding sibling and clicking on it.
        driver.findElement(By.xpath("//li[@class='login']//preceding-sibling::li[1]")).click();
        
        //Verifying the current URL on which we post clicking on it.
        String currentURL= driver.getCurrentUrl();
        System.out.println(currentURL);
        
        driver.close();

    }

}
Console Output
5. Child: As the name specified this approach is used when we intend to locate all child elements of the current node. A basic use case of this approach could be when we wish to circulate all the data in a table through the rows, in this case we can find all the children of a particular table. For example, using the below referenced DOM structure, we can create an XPath in Selenium as follows:
<div class="col-sm-12 google-sign-form"><input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 "> <input type="text" placeholder="Full Name*" name="name" value="" class="form-control sign-up-input-2 "> <input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 "> <input type="password" placeholder="Desired Password*" name="password" class="form-control sign-up-input-2 "> <input type="phone" placeholder="Phone*" name="phone" value="" class="form-control sign-up-input-2 "> <p class="terms-cond"><label for="terms_of_service" class="woo"><input type="checkbox" name="terms_of_service" id="terms_of_service" value="1" class="form-check-input" style="position: relative; margin-left: 0px;"> &nbsp; I agree to the <a target="_blank" href="https://www.lambdatest.com/terms-of-service">Terms
                                    of Service</a>
                                and <a target="_blank" href="https://www.lambdatest.com/privacy">Privacy Policy</a></label></p> <button type="submit" class=" btn sign-up-btn-2 btn-block">Signup for Free</button></div>
Referenced screenshot of the same.
  • Xpath= //div[@class=’ col-sm-12 google-sign-form’]/child::input
  • Xpath= //div[@class=’ col-sm-12 google-sign-form’]/child::input[1]
In the above-mentioned example, the first will locate all the input fields of the div for which are organization field, name field, email field, password field and phone number field, whereas the other is used to locate element with the organization field only.
Below is the code snippet highlighting the use of child axes on the same. We are using the same register example of LambdaTest register page.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingChild {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path of chrome driver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://accounts.lambdatest.com/register");
        driver.manage().window().maximize();
        
        //Finding the work email filed using the child locator xpath axes
        driver.findElement(By.xpath("//div[@class='col-sm-12 google-sign-form']/child::input[3]")).sendKeys("sadhvi singh");;
        
        driver.close();

    }

}
6. Parent: This method is used to select the parent node of the current node. For example, for the below referenced DOM structure, the parent node is located through XPath.
<div class="col-sm-12 google-sign-form"><input type="text" placeholder="Organization/Company Name" name="organization_name" value="" class="form-control sign-up-input-2 "> <input type="text" placeholder="Full Name*" name="name" value="" class="form-control sign-up-input-2 "> <input type="email" placeholder="Work Email*" name="email" value="" class="form-control sign-up-input-2 "> <input type="password" placeholder="Desired Password*" name="password" class="form-control sign-up-input-2 "> <input type="phone" placeholder="Phone*" name="phone" value="" class="form-control sign-up-input-2 "> <p class="terms-cond"><label for="terms_of_service" class="woo"><input type="checkbox" name="terms_of_service" id="terms_of_service" value="1" class="form-check-input" style="position: relative; margin-left: 0px;"> &nbsp; I agree to the <a target="_blank" href="https://www.lambdatest.com/terms-of-service">Terms
                                    of Service</a>
                                and <a target="_blank" href="https://www.lambdatest.com/privacy">Privacy Policy</a></label></p> < button type="submit" class=" btn sign-up-btn-2 btn-block">Signup for Free< /button ></div>
Referenced screenshot:
  • Xpath= //input[@name=’email’]//parent::div
In the above example, the parent element is located through its child element. From the email field we are traversing to its parent node. Please note in case of child XPath, only the immediate children of the current node are considered and not the grandchildren. In case if the current node is the root node, then its parent will be empty and hence it will have no parent aces. Below is the code snippet for the same:
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingParent {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path of chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
               driver.get("https://accounts.lambdatest.com/register");
               driver.manage().window().maximize();
        
        //Finding the parent form usnig the password field as the current node.
        WebElement parentDiv=driver.findElement(By.xpath("//input[@name='password']//parent::div"));
        System.out.print(parentDiv.getAttribute("class"));
        
        driver.close();

    }

}
Console Output
7. Descendants: This approach is used to locate elements via XPath for all the children and sub children of the current node. For the below DOM structure, the descendants for XPath in Selenium are located as:
<div class="col-lg-3 col-md-4 col-sm-6 sign-form"><a href="https://www.lambdatest.com"><img height="38" src="/images/logo.svg" class="img-responsive mb-4 mx-auto d-block"></a> <h1 class="title text-center font-weight-light">Hello! Welcome back</h1> <input type="email" name="email" value="" placeholder="Email" required="required" autofocus="autofocus" class="form-control mt-3 form-control-lg"> <input type="password" name="password" placeholder="Password" class="form-control mt-3 form-control-lg"> <button type="submit" class="btn btn-primary btn-lg btn-block mt-3">LOGIN</button> <div class="form-group form-check mt-2"><input type="checkbox" name="remember" id="remember" class="form-check-input"> <label for="remember" class="form-check-label">Remember Me</label></div> <div class="row mt-2"><div class="col pr-2 text-pass"><a href="https://accounts.lambdatest.com/password/reset">Forgot Password?</a></div> <div class="col pl-2 text-pass text-right">No account? <a href="/register">Sign up</a></div></div></div>
Referenced Screenshot:
  • Xpath= //div[@class=’ col-lg-3 col-md-4 col-sm-6 sign-form’]//descendant:: input
In the example above all the elements like email field, password field and button will be selected. One can also select one of the mentioned fields using index. Below is a code snippet highlighting the use of it.
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingDescendants {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path of chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://accounts.lambdatest.com/login");
        driver.manage().window().maximize();
        
        //Finding the remember me grandchildren of the login form with field value as remember me.
        WebElement rememberMe=driver.findElement(By.xpath("//div[@class='col-lg-3 col-md-4 col-sm-6 sign-form']//descendant::label"));
        rememberMe.click();
        System.out.print(rememberMe.getText());
        
        driver.close();


    }

}
Console Output
8. Ancestors: In this method the context node, parent or its grandparents are selected via the Ancestors axes. For example, for the below DOM structure the ancestor will be defined as:
 <form method="POST" action="https://accounts.lambdatest.com/login"><input type="hidden" name="_token" value="W4D7bCygQ4abq2Xa3ckZ2rwG3Wk7f9enPXIIPeuF"> <div class="row justify-content-sm-center"><div class="col-lg-3 col-md-4 col-sm-6 sign-form"><a href="https://www.lambdatest.com"><img height="38" src="/images/logo.svg" class="img-responsive mb-4 mx-auto d-block"></a> <h1 class="title text-center font-weight-light">Hello! Welcome back</h1> <input type="email" name="email" value="" placeholder="Email" required="required" autofocus="autofocus" class="form-control mt-3 form-control-lg"> <input type="password" name="password" placeholder="Password" class="form-control mt-3 form-control-lg"> <button type="submit" class="btn btn-primary btn-lg btn-block mt-3">LOGIN</button> <div class="form-group form-check mt-2"><input type="checkbox" name="remember" id="remember" class="form-check-input"> <label for="remember" class="form-check-label">Remember Me</label></div> <div class="row mt-2"><div class="col pr-2 text-pass"><a href="https://accounts.lambdatest.com/password/reset">Forgot Password?</a></div> <div class="col pl-2 text-pass text-right">No account? <a href="/register">Sign up</a></div></div></div></div></form>
Referenced screenshot:
  • Xpath= //input[@name=’email]//ancestor::div[1]
  • Xpath= //input[@name=’email]//ancestor::form
In the example above, the first one will point to the parent node of the login fields where the other will point to its grandparent node which is the tag form in this case. Below code snippet highlighting the use of the same.
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class XpathUsingAncestor {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        System.setProperty("webdriver.chrome.driver", "path of chromedriver");
        WebDriver driver=new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://accounts.lambdatest.com/login");
        driver.manage().window().maximize();
        
        //Finding the parent div using the password field of the login page.
        WebElement parentDiv=driver.findElement(By.xpath("//input[@name='password']//ancestor::div[1]"));
        System.out.println(parentDiv.getAttribute("class"));
        
        WebElement parentForm=driver.findElement(By.xpath("//input[@name='password']//ancestor::form"));
        System.out.println(parentForm.getAttribute("action"));
        
        
        driver.close();


    }

}
Console Output

Conclusion

XPath in Selenium helps an individual find out solutions in locating elements when the standard processes do not work. When to use which is important when it comes to different complexities of the DOM structure and the functional needs. As defined earlier in my article, cross browser testing could be one of the areas where you can explore the creation of XPath in Selenium, due to different browser behaviors towards DOM elements. Make sure whichever method you opt in case of XPath are less prone to failure and make the scripts more robust, neater and easier to maintain. 
Cheers!

Written by Rahul Jain | Automation Testing Enthusiast
Published by HackerNoon on 2020/11/09