XPath axes let you navigate the DOM tree in any direction — up to a parent, down to a child, sideways to a sibling. This is what makes XPath more powerful than CSS selectors. CSS can only go down (child/descendant) and sideways to the next sibling. XPath can go everywhere.
// parent:: — go up ONE level
driver.findElement(By.xpath(
"//span[@class='error-message']/parent::div"));
// Find the div that contains an error message
driver.findElement(By.xpath(
"//button[@data-testid='loginBtn']/parent::form"));
// Find the form that contains the login button
// ancestor:: — go up to ANY ancestor (parent, grandparent, etc.)
driver.findElement(By.xpath(
"//span[@data-testid='product-name-1']/ancestor::div[@data-testid='product-item']"));
// From product name → go up to the product card// following-sibling:: — find siblings AFTER this element
driver.findElement(By.xpath(
"//label[text()='Password']/following-sibling::div//input"));
// Find the input that comes after the "Password" label
// preceding-sibling:: — find siblings BEFORE this element
driver.findElement(By.xpath(
"//input[@id='password']/preceding-sibling::label"));
// Find the label before the password input
// CSS can do following sibling (+) but NOT preceding sibling
// This is a major reason to use XPath// child:: — direct children only
driver.findElements(By.xpath(
"//div[@data-testid='product-list']/child::div"));
// descendant:: — children at ANY depth
driver.findElements(By.xpath("//form//descendant::input"));
// following:: — ANY element after this one (not just siblings)
driver.findElement(By.xpath(
"//h2[text()='Recent Transactions']/following::table"));
// preceding:: — ANY element before this one
driver.findElement(By.xpath("//table/preceding::h2"));// XPath indexes are 1-based (not 0-based like CSS)
// Get the 2nd product card
driver.findElement(By.xpath(
"(//div[@data-testid='product-item'])[2]"));
// Get the LAST product card
driver.findElement(By.xpath(
"(//div[@data-testid='product-item'])[last()]"));
// Get the first 3 table rows
driver.findElements(By.xpath("//table//tr[position()<=3]"));
// Get the last row
driver.findElement(By.xpath("//table//tr[last()]"));// Banking Portal
// Find the form that contains the Sign In button
driver.findElement(By.xpath(
"//button[text()='Sign In']/ancestor::form"));
// Find the "View Statement" link on dashboard
driver.findElement(By.xpath("//a[text()='View Statement']"));
// Find Fund Transfer quick action by its label
driver.findElement(By.xpath(
"//p[text()='Fund Transfer']/ancestor::a"));
// Get a specific column from a transaction row
driver.findElement(By.xpath(
"//tr[@data-testid='txnRow-0']/td[2]"));
// Shopping Portal
// Find Add to Cart button for a specific product
driver.findElement(By.xpath(
"//span[contains(text(), 'Phone')]/ancestor::div[@data-testid='product-item']//button[contains(@class, 'add-to-cart')]"));
// Find all in-stock products
driver.findElements(By.xpath(
"//span[text()='In Stock']/ancestor::div[@data-testid='product-item']"));The most useful XPath pattern in real projects: start from a text you can see → go UP to the container with ancestor:: → go DOWN to the element you need. Like: //span[text()="Phone"]/ancestor::div[@class="card"]//button — find the button inside the card that contains "Phone".
Key Point: XPath axes let you go up (parent/ancestor), down (child/descendant), and sideways (sibling). CSS can only go down and to the next sibling.