<div class="selenium-notes">
<h1>XPath in Selenium</h1>
<p><strong>XPath</strong> stands for <strong>XML Path Language</strong>. In Selenium WebDriver, XPath is a powerful locator strategy used to identify and interact with web elements in an HTML DOM. XPath can locate elements using attributes, text, relationships between elements, indexes, and different axes.</p>
<p>XPath is especially useful when an element does not have a unique ID, Name, or Class Name, or when the tester needs to create a more flexible locator for dynamic web applications. Selenium WebDriver supports XPath through the <strong>By.xpath()</strong> method.</p>
<p>XPath is included among the locator strategies covered in Selenium training, along with ID and CSS selectors, and is used for locating web elements in practical browser automation. <a href="https://www.justacademy.co/course-detail/selenium-training" target="_blank" rel="noopener noreferrer">JustAcademy's Selenium Training Course</a> also covers Selenium WebDriver, locators, web elements, forms, browser interactions, waits, and automation frameworks.</p>
<p>For course demonstration and registration information, visit the <a href="https://www.justacademy.co/register-for-course-demo" target="_blank" rel="noopener noreferrer">Register for Course Demo</a> page.</p>
<hr>
<h2>1. What is XPath?</h2>
<p>XPath is a query language used to navigate through elements and attributes in an XML or HTML document. Selenium uses XPath expressions to locate elements in the DOM.</p>
<p>For example, consider:</p>
<pre><code><input id="username" name="username" type="text"></code></pre>
<p>An XPath locator for this element can be:</p>
<pre><code>//input[@id='username']</code></pre>
<p>Selenium code:</p>
<pre><code>driver.findElement(
By.xpath("//input[@id='username']")
);</code></pre>
<hr>
<h2>2. Why XPath is Important in Selenium</h2>
<p>XPath is important because modern web applications often contain complex and dynamic DOM structures. Simple locators may not always be sufficient to identify the required element.</p>
<ul>
<li>XPath can locate elements using attributes.</li>
<li>XPath can locate elements using visible text.</li>
<li>XPath can locate elements using partial attribute values.</li>
<li>XPath can navigate parent-child relationships.</li>
<li>XPath can navigate sibling relationships.</li>
<li>XPath can locate elements based on surrounding elements.</li>
<li>XPath can handle many dynamic element scenarios.</li>
<li>XPath can use indexes when necessary.</li>
<li>XPath can locate elements inside complex DOM structures.</li>
<li>XPath is useful when unique IDs or names are unavailable.</li>
</ul>
<hr>
<h2>3. Basic XPath Syntax</h2>
<p>The most common XPath syntax is:</p>
<pre><code>//tagname[@attribute='value']</code></pre>
<p>Example:</p>
<pre><code>//input[@name='username']</code></pre>
<p>Another example:</p>
<pre><code>//button[@type='submit']</code></pre>
<hr>
<h2>4. XPath in Selenium</h2>
<p>Selenium uses the <code>By.xpath()</code> method to locate an element.</p>
<pre><code>driver.findElement(
By.xpath("//input[@id='username']")
);</code></pre>
<p>The general structure is:</p>
<pre><code>driver.findElement(By.xpath("XPATH_EXPRESSION"));</code></pre>
<hr>
<h2>5. Required Selenium Imports</h2>
<pre><code>import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;</code></pre>
<hr>
<h2>6. Basic XPath Example</h2>
<pre><code>import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class XPathExample {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://example.com");
driver.findElement(
By.xpath("//input[@id='username']")
).sendKeys("admin");
driver.quit();
}
}</code></pre>
<hr>
<h2>7. Understanding the DOM</h2>
<p>XPath works with the DOM structure of a web page. The browser converts HTML into a tree-like structure containing elements, attributes, text nodes, and relationships.</p>
<pre><code>HTML
|
+-- BODY
|
+-- FORM
|
+-- INPUT
|
+-- INPUT
|
+-- BUTTON</code></pre>
<p>XPath allows Selenium to navigate this structure and identify a specific element.</p>
<hr>
<h2>8. Absolute XPath</h2>
<p>An <strong>Absolute XPath</strong> starts from the root of the HTML document and specifies the complete path to an element.</p>
<pre><code>/html/body/div/form/input</code></pre>
<p>Absolute XPath can become fragile because even a small change in the DOM structure can make the locator invalid.</p>
<hr>
<h2>9. Relative XPath</h2>
<p>A <strong>Relative XPath</strong> usually starts with <code>//</code> and searches for an element based on its characteristics rather than describing the complete path from the root.</p>
<pre><code>//input[@id='username']</code></pre>
<p>Relative XPath is generally easier to maintain because it does not depend on the complete DOM hierarchy.</p>
<hr>
<h2>10. Absolute XPath vs Relative XPath</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Feature</th><th>Absolute XPath</th><th>Relative XPath</th></tr>
<tr><td>Starts with</td><td>/</td><td>//</td></tr>
<tr><td>DOM dependency</td><td>High</td><td>Lower</td></tr>
<tr><td>Maintenance</td><td>Can be difficult</td><td>Generally easier</td></tr>
<tr><td>Flexibility</td><td>Limited</td><td>High</td></tr>
<tr><td>Typical usage</td><td>Specific full path</td><td>Practical automation locators</td></tr>
</table>
<hr>
<h2>11. XPath Using ID</h2>
<p>Suppose the HTML is:</p>
<pre><code><input id="username" type="text"></code></pre>
<p>XPath:</p>
<pre><code>//input[@id='username']</code></pre>
<p>Selenium:</p>
<pre><code>driver.findElement(
By.xpath("//input[@id='username']")
).sendKeys("admin");</code></pre>
<hr>
<h2>12. XPath Using Name</h2>
<pre><code><input name="email" type="email"></code></pre>
<p>XPath:</p>
<pre><code>//input[@name='email']</code></pre>
<p>Selenium:</p>
<pre><code>driver.findElement(
By.xpath("//input[@name='email']")
).sendKeys("[email protected]");</code></pre>
<hr>
<h2>13. XPath Using Class</h2>
<pre><code><button class="login-button">Login</button></code></pre>
<p>XPath:</p>
<pre><code>//button[@class='login-button']</code></pre>
<hr>
<h2>14. XPath Using Type Attribute</h2>
<pre><code><input type="password"></code></pre>
<p>XPath:</p>
<pre><code>//input[@type='password']</code></pre>
<hr>
<h2>15. XPath Using Value Attribute</h2>
<pre><code><input type="submit" value="Login"></code></pre>
<p>XPath:</p>
<pre><code>//input[@value='Login']</code></pre>
<hr>
<h2>16. XPath Using Placeholder</h2>
<pre><code><input placeholder="Enter Username" type="text"></code></pre>
<p>XPath:</p>
<pre><code>//input[@placeholder='Enter Username']</code></pre>
<hr>
<h2>17. XPath Using Multiple Attributes</h2>
<p>Multiple attributes can be combined using the <code>and</code> operator.</p>
<pre><code>//input[@type='text' and @name='username']</code></pre>
<p>Another example:</p>
<pre><code>//input[@type='text' and @name='username' and @placeholder='Enter Username']</code></pre>
<hr>
<h2>18. XPath Using OR Condition</h2>
<p>The <code>or</code> operator can be used when either of multiple conditions can identify the element.</p>
<pre><code>//input[@id='username' or @name='username']</code></pre>
<p>This XPath matches an input whose ID is username or whose name is username.</p>
<hr>
<h2>19. XPath Using Text</h2>
<p>The <code>text()</code> function is useful for locating elements based on their exact visible text.</p>
<pre><code><button>Login</button></code></pre>
<p>XPath:</p>
<pre><code>//button[text()='Login']</code></pre>
<p>Selenium:</p>
<pre><code>driver.findElement(
By.xpath("//button[text()='Login']")
).click();</code></pre>
<hr>
<h2>20. XPath Using Partial Text with contains()</h2>
<p>The <code>contains()</code> function is useful when only part of the text is stable.</p>
<pre><code><button>Login to Account</button></code></pre>
<p>XPath:</p>
<pre><code>//button[contains(text(),'Login')]</code></pre>
<hr>
<h2>21. XPath contains() Function</h2>
<p>The <code>contains()</code> function can be used with attributes as well as text.</p>
<p>Attribute example:</p>
<pre><code>//input[contains(@id,'user')]</code></pre>
<p>Text example:</p>
<pre><code>//button[contains(text(),'Login')]</code></pre>
<p>Class example:</p>
<pre><code>//div[contains(@class,'container')]</code></pre>
<hr>
<h2>22. XPath starts-with() Function</h2>
<p>The <code>starts-with()</code> function identifies elements whose attribute value or text starts with a specified value.</p>
<pre><code>//input[starts-with(@id,'user_')]</code></pre>
<p>This is useful for dynamic IDs such as:</p>
<pre><code>user_12345
user_93842
user_84729</code></pre>
<hr>
<h2>23. XPath normalize-space()</h2>
<p>The <code>normalize-space()</code> function removes leading and trailing whitespace and normalizes consecutive whitespace characters.</p>
<pre><code>//button[normalize-space()='Login']</code></pre>
<p>This can be useful when HTML contains unexpected spaces around visible text.</p>
<hr>
<h2>24. normalize-space() with Partial Text</h2>
<pre><code>//button[contains(normalize-space(),'Login')]</code></pre>
<hr>
<h2>25. XPath with and</h2>
<pre><code>//input[@type='text' and @name='username']</code></pre>
<p>Both conditions must match.</p>
<hr>
<h2>26. XPath with or</h2>
<pre><code>//input[@id='username' or @name='username']</code></pre>
<p>At least one condition must match.</p>
<hr>
<h2>27. XPath with not()</h2>
<p>The <code>not()</code> function can exclude elements matching a particular condition.</p>
<pre><code>//input[not(@type='hidden')]</code></pre>
<p>This selects input elements that do not have type equal to hidden.</p>
<hr>
<h2>28. XPath Using Multiple Conditions with contains()</h2>
<pre><code>//button[contains(@class,'btn') and contains(@class,'login')]</code></pre>
<hr>
<h2>29. XPath Indexing</h2>
<p>XPath supports indexes for selecting a particular matching element.</p>
<pre><code>(//input[@type='text'])[1]</code></pre>
<p>Second matching element:</p>
<pre><code>(//input[@type='text'])[2]</code></pre>
<hr>
<h2>30. XPath Indexing Example</h2>
<pre><code><input type="text" name="first">
<input type="text" name="second">
<input type="text" name="third"></code></pre>
<p>First input:</p>
<pre><code>(//input[@type='text'])[1]</code></pre>
<p>Second input:</p>
<pre><code>(//input[@type='text'])[2]</code></pre>
<hr>
<h2>31. XPath Position()</h2>
<p>The <code>position()</code> function can be used to identify an element based on its position.</p>
<pre><code>//input[@type='text'][position()=1]</code></pre>
<p>Second element:</p>
<pre><code>//input[@type='text'][position()=2]</code></pre>
<hr>
<h2>32. XPath last()</h2>
<p>The <code>last()</code> function identifies the last matching element.</p>
<pre><code>//input[@type='text'][last()]</code></pre>
<hr>
<h2>33. XPath Parent Axis</h2>
<p>The <code>parent</code> axis selects the parent of the current element.</p>
<pre><code>//input[@id='username']/parent::div</code></pre>
<hr>
<h2>34. XPath Parent Using ..</h2>
<p>The <code>..</code> notation can be used to move to the parent element.</p>
<pre><code>//input[@id='username']/..</code></pre>
<hr>
<h2>35. XPath Child Axis</h2>
<p>The <code>child</code> axis selects child elements.</p>
<pre><code>//div[@id='login']/child::input</code></pre>
<p>Equivalent shorter form:</p>
<pre><code>//div[@id='login']/input</code></pre>
<hr>
<h2>36. XPath Descendant Axis</h2>
<p>The <code>descendant</code> axis selects elements located anywhere below the current element.</p>
<pre><code>//div[@id='login']/descendant::input</code></pre>
<p>Shorter form:</p>
<pre><code>//div[@id='login']//input</code></pre>
<hr>
<h2>37. XPath Ancestor Axis</h2>
<p>The <code>ancestor</code> axis selects ancestor elements of the current element.</p>
<pre><code>//input[@id='username']/ancestor::form</code></pre>
<hr>
<h2>38. XPath Following-Sibling</h2>
<p>The <code>following-sibling</code> axis selects siblings that appear after the current element.</p>
<pre><code>//label[text()='Username']/following-sibling::input</code></pre>
<hr>
<h2>39. XPath Preceding-Sibling</h2>
<p>The <code>preceding-sibling</code> axis selects siblings that appear before the current element.</p>
<pre><code>//input[@id='username']/preceding-sibling::label</code></pre>
<hr>
<h2>40. XPath Following Axis</h2>
<p>The <code>following</code> axis selects elements appearing later in the document, excluding descendants.</p>
<pre><code>//label[text()='Username']/following::input</code></pre>
<hr>
<h2>41. XPath Preceding Axis</h2>
<p>The <code>preceding</code> axis selects elements appearing before the current element.</p>
<pre><code>//input[@id='password']/preceding::label</code></pre>
<hr>
<h2>42. XPath Self Axis</h2>
<p>The <code>self</code> axis refers to the current node.</p>
<pre><code>//input[@id='username']/self::input</code></pre>
<hr>
<h2>43. XPath Descendant-or-Self</h2>
<pre><code>//div[@id='container']/descendant-or-self::div</code></pre>
<hr>
<h2>44. XPath Ancestor-or-Self</h2>
<pre><code>//input[@id='username']/ancestor-or-self::input</code></pre>
<hr>
<h2>45. XPath Axes Reference</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Axis</th><th>Purpose</th></tr>
<tr><td>ancestor</td><td>Selects ancestors</td></tr>
<tr><td>ancestor-or-self</td><td>Selects ancestors and current node</td></tr>
<tr><td>attribute</td><td>Selects attributes</td></tr>
<tr><td>child</td><td>Selects direct children</td></tr>
<tr><td>descendant</td><td>Selects descendants</td></tr>
<tr><td>descendant-or-self</td><td>Selects descendants and current node</td></tr>
<tr><td>following</td><td>Selects nodes later in the document</td></tr>
<tr><td>following-sibling</td><td>Selects following siblings</td></tr>
<tr><td>parent</td><td>Selects parent</td></tr>
<tr><td>preceding</td><td>Selects preceding nodes</td></tr>
<tr><td>preceding-sibling</td><td>Selects preceding siblings</td></tr>
<tr><td>self</td><td>Selects current node</td></tr>
</table>
<hr>
<h2>46. XPath Using Parent-Child Relationship</h2>
<pre><code><div class="login-form">
<input name="username">
</div></code></pre>
<p>XPath:</p>
<pre><code>//div[@class='login-form']/input[@name='username']</code></pre>
<hr>
<h2>47. XPath Using Nested Elements</h2>
<pre><code><div class="container">
<div class="form">
<input name="email">
</div>
</div></code></pre>
<p>XPath:</p>
<pre><code>//div[@class='container']//input[@name='email']</code></pre>
<hr>
<h2>48. XPath Using Label Relationship</h2>
<pre><code><label>Username</label>
<input type="text" name="username"></code></pre>
<p>XPath:</p>
<pre><code>//label[text()='Username']/following-sibling::input</code></pre>
<hr>
<h2>49. XPath for Form Elements</h2>
<pre><code>//form[@id='registration']//input[@name='email']</code></pre>
<p>This identifies an email field within a specific registration form.</p>
<hr>
<h2>50. XPath for Buttons</h2>
<pre><code>//button[@type='submit']</code></pre>
<p>Using text:</p>
<pre><code>//button[text()='Submit']</code></pre>
<p>Using partial text:</p>
<pre><code>//button[contains(text(),'Submit')]</code></pre>
<hr>
<h2>51. XPath for Links</h2>
<pre><code>//a[@href='/login']</code></pre>
<p>Using text:</p>
<pre><code>//a[text()='Login']</code></pre>
<p>Using partial text:</p>
<pre><code>//a[contains(text(),'Login')]</code></pre>
<hr>
<h2>52. XPath for Checkboxes</h2>
<pre><code>//input[@type='checkbox' and @name='terms']</code></pre>
<p>Selenium:</p>
<pre><code>WebElement checkbox = driver.findElement(
By.xpath("//input[@type='checkbox' and @name='terms']")
);
if (!checkbox.isSelected()) {
checkbox.click();
}</code></pre>
<hr>
<h2>53. XPath for Radio Buttons</h2>
<pre><code>//input[@type='radio' and @value='male']</code></pre>
<p>Selenium:</p>
<pre><code>driver.findElement(
By.xpath("//input[@type='radio' and @value='male']")
).click();</code></pre>
<hr>
<h2>54. XPath for Dropdown</h2>
<pre><code><select id="country">
<option value="india">India</option>
<option value="usa">USA</option>
</select></code></pre>
<p>Select element:</p>
<pre><code>//select[@id='country']</code></pre>
<p>India option:</p>
<pre><code>//select[@id='country']/option[@value='india']</code></pre>
<hr>
<h2>55. XPath for Images</h2>
<pre><code><img src="/images/logo.png" alt="Company Logo"></code></pre>
<p>XPath:</p>
<pre><code>//img[@alt='Company Logo']</code></pre>
<hr>
<h2>56. XPath for Tables</h2>
<pre><code><table id="users">
<tr>
<td>John</td>
<td>[email protected]</td>
</tr>
</table></code></pre>
<p>Table:</p>
<pre><code>//table[@id='users']</code></pre>
<p>Rows:</p>
<pre><code>//table[@id='users']//tr</code></pre>
<p>Cells:</p>
<pre><code>//table[@id='users']//tr//td</code></pre>
<hr>
<h2>57. XPath for Specific Table Row</h2>
<p>Suppose a table contains product names:</p>
<pre><code><table id="products">
<tr>
<td>Laptop</td>
<td>1000</td>
</tr>
<tr>
<td>Phone</td>
<td>700</td>
</tr>
</table></code></pre>
<p>Row containing Laptop:</p>
<pre><code>//table[@id='products']//tr[td[text()='Laptop']]</code></pre>
<hr>
<h2>58. XPath for Button in Specific Table Row</h2>
<pre><code>//table[@id='products']//tr[td[text()='Laptop']]//button</code></pre>
<p>This is useful for actions such as Edit, Delete, View, or Add to Cart for a specific table row.</p>
<hr>
<h2>59. XPath for Dynamic IDs</h2>
<p>Suppose an application generates:</p>
<pre><code><input id="user_847392"></code></pre>
<p>If the stable portion is <code>user_</code>, use:</p>
<pre><code>//input[starts-with(@id,'user_')]</code></pre>
<p>Or:</p>
<pre><code>//input[contains(@id,'user_')]</code></pre>
<hr>
<h2>60. XPath for Dynamic Class</h2>
<pre><code><button class="btn-submit-8392">Submit</button></code></pre>
<p>XPath:</p>
<pre><code>//button[contains(@class,'btn-submit')]</code></pre>
<hr>
<h2>61. XPath Using Multiple Stable Attributes</h2>
<pre><code>//input[contains(@class,'form-control') and @name='email']</code></pre>
<p>Combining stable attributes can reduce the chance of matching the wrong element.</p>
<hr>
<h2>62. XPath for Dynamic Text</h2>
<p>Suppose the text is:</p>
<pre><code>Welcome, John</code></pre>
<p>A partial text XPath can be:</p>
<pre><code>//div[contains(text(),'Welcome')]</code></pre>
<p>For whitespace variations:</p>
<pre><code>//div[contains(normalize-space(),'Welcome')]</code></pre>
<hr>
<h2>63. XPath for Text with Extra Spaces</h2>
<pre><code><button> Login </button></code></pre>
<p>Instead of depending on the exact whitespace:</p>
<pre><code>//button[normalize-space()='Login']</code></pre>
<hr>
<h2>64. XPath for Partial Attribute Value</h2>
<pre><code>//input[contains(@placeholder,'Username')]</code></pre>
<hr>
<h2>65. XPath Using Starts-With for URLs</h2>
<pre><code>//a[starts-with(@href,'/products')]</code></pre>
<p>This can identify links whose href starts with a known path.</p>
<hr>
<h2>66. XPath for Multiple Matching Elements</h2>
<p>When several elements match the same XPath, Selenium's <code>findElement()</code> returns the first matching element according to the WebDriver element search.</p>
<pre><code>driver.findElement(
By.xpath("//button[@class='btn']")
);</code></pre>
<p>If you need all matching elements, use <code>findElements()</code>.</p>
<hr>
<h2>67. XPath with findElements()</h2>
<pre><code>List<WebElement> buttons = driver.findElements(
By.xpath("//button")
);</code></pre>
<hr>
<h2>68. Count Elements Using XPath</h2>
<pre><code>List<WebElement> links = driver.findElements(
By.xpath("//a")
);
System.out.println(
"Number of links: " + links.size()
);</code></pre>
<hr>
<h2>69. Loop Through XPath Results</h2>
<pre><code>List<WebElement> links = driver.findElements(
By.xpath("//nav//a")
);
for (WebElement link : links) {
System.out.println(link.getText());
}</code></pre>
<hr>
<h2>70. XPath with Explicit Wait</h2>
<pre><code>WebDriverWait wait =
new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement loginButton = wait.until(
ExpectedConditions.elementToBeClickable(
By.xpath("//button[@type='submit']")
)
);
loginButton.click();</code></pre>
<hr>
<h2>71. Required Imports for Explicit Wait</h2>
<pre><code>import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;</code></pre>
<hr>
<h2>72. XPath with Visibility Wait</h2>
<pre><code>WebElement dashboard = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.xpath("//div[@id='dashboard']")
)
);</code></pre>
<hr>
<h2>73. XPath with Presence Wait</h2>
<pre><code>WebElement element = wait.until(
ExpectedConditions.presenceOfElementLocated(
By.xpath("//input[@name='username']")
)
);</code></pre>
<hr>
<h2>74. XPath with Clickable Wait</h2>
<pre><code>WebElement button = wait.until(
ExpectedConditions.elementToBeClickable(
By.xpath("//button[contains(text(),'Login')]")
)
);
button.click();</code></pre>
<hr>
<h2>75. XPath and Implicit Wait</h2>
<pre><code>driver.manage().timeouts().implicitlyWait(
Duration.ofSeconds(10)
);</code></pre>
<p>After configuring the wait, XPath can be used normally with <code>findElement()</code>.</p>
<hr>
<h2>76. XPath and Dynamic Web Applications</h2>
<p>Dynamic applications may generate changing IDs, classes, text, and DOM structures. XPath functions such as <code>contains()</code>, <code>starts-with()</code>, and <code>normalize-space()</code> can help create more flexible locators.</p>
<pre><code>//input[contains(@id,'user')]
//button[contains(@class,'submit')]
//div[normalize-space()='Login']</code></pre>
<hr>
<h2>77. XPath for Login Form</h2>
<pre><code><form id="loginForm">
<input name="username" type="text">
<input name="password" type="password">
<button type="submit">Login</button>
</form></code></pre>
<p>Username:</p>
<pre><code>//form[@id='loginForm']//input[@name='username']</code></pre>
<p>Password:</p>
<pre><code>//form[@id='loginForm']//input[@name='password']</code></pre>
<p>Login button:</p>
<pre><code>//form[@id='loginForm']//button[@type='submit']</code></pre>
<hr>
<h2>78. Complete Login Automation Using XPath</h2>
<pre><code>driver.findElement(
By.xpath("//input[@name='username']")
).sendKeys("admin");
driver.findElement(
By.xpath("//input[@name='password']")
).sendKeys("admin123");
driver.findElement(
By.xpath("//button[@type='submit']")
).click();</code></pre>
<hr>
<h2>79. XPath for Registration Form</h2>
<pre><code>driver.findElement(
By.xpath("//input[@name='firstName']")
).sendKeys("John");
driver.findElement(
By.xpath("//input[@name='lastName']")
).sendKeys("Smith");
driver.findElement(
By.xpath("//input[@type='email']")
).sendKeys("[email protected]");
driver.findElement(
By.xpath("//input[@type='password']")
).sendKeys("Password123");
driver.findElement(
By.xpath("//button[@type='submit']")
).click();</code></pre>
<hr>
<h2>80. XPath for E-Commerce Product</h2>
<pre><code><div class="product-card">
<h3>Laptop</h3>
<button>Add to Cart</button>
</div></code></pre>
<p>Product:</p>
<pre><code>//div[contains(@class,'product-card')][.//h3[text()='Laptop']]</code></pre>
<p>Add to Cart button for Laptop:</p>
<pre><code>//div[contains(@class,'product-card')][.//h3[text()='Laptop']]//button[contains(text(),'Add to Cart')]</code></pre>
<hr>
<h2>81. XPath for Navigation Links</h2>
<pre><code>//nav//a[@href='/courses']</code></pre>
<p>Using text:</p>
<pre><code>//nav//a[normalize-space()='Courses']</code></pre>
<hr>
<h2>82. XPath for Modal</h2>
<pre><code><div id="loginModal" class="modal">
<input name="username">
</div></code></pre>
<p>Username inside modal:</p>
<pre><code>//div[@id='loginModal']//input[@name='username']</code></pre>
<hr>
<h2>83. XPath for Alert Message</h2>
<pre><code><div class="alert-success">Login successful</div></code></pre>
<p>XPath:</p>
<pre><code>//div[contains(@class,'alert-success')]</code></pre>
<p>Using text:</p>
<pre><code>//div[contains(text(),'Login successful')]</code></pre>
<hr>
<h2>84. XPath for Error Message</h2>
<pre><code>//div[contains(@class,'error-message')]</code></pre>
<p>Or:</p>
<pre><code>//div[contains(normalize-space(),'Invalid password')]</code></pre>
<hr>
<h2>85. XPath for Checkbox State</h2>
<p>XPath can locate a checkbox using its attributes. Selenium's <code>isSelected()</code> method is normally used to verify its current state.</p>
<pre><code>WebElement checkbox = driver.findElement(
By.xpath("//input[@type='checkbox' and @name='terms']")
);
if (checkbox.isSelected()) {
System.out.println("Checkbox is selected");
}</code></pre>
<hr>
<h2>86. XPath for Radio Button State</h2>
<pre><code>WebElement radio = driver.findElement(
By.xpath("//input[@type='radio' and @value='male']")
);
if (radio.isSelected()) {
System.out.println("Male radio button is selected");
}</code></pre>
<hr>
<h2>87. XPath for Selected Radio Button</h2>
<p>For HTML form controls, XPath can sometimes be used with attributes such as <code>@checked</code>, but the presence of the attribute and the current DOM state are not always interchangeable. Selenium's <code>isSelected()</code> method is the preferred way to verify the current selected state.</p>
<hr>
<h2>88. XPath for Disabled Element</h2>
<pre><code>//button[@disabled]</code></pre>
<p>Selenium can then verify whether the element is enabled:</p>
<pre><code>WebElement button = driver.findElement(
By.xpath("//button[@disabled]")
);
System.out.println(button.isEnabled());</code></pre>
<hr>
<h2>89. XPath for Required Elements</h2>
<pre><code>//input[@required]</code></pre>
<hr>
<h2>90. XPath for Elements with Specific Data Attributes</h2>
<pre><code>//button[@data-testid='login-button']</code></pre>
<p>Data attributes can provide stable locator values when they are intentionally designed for automation or testing.</p>
<hr>
<h2>91. XPath with data-testid</h2>
<pre><code><button data-testid="submit-button">Submit</button></code></pre>
<p>XPath:</p>
<pre><code>//button[@data-testid='submit-button']</code></pre>
<hr>
<h2>92. XPath with aria-label</h2>
<pre><code><button aria-label="Search">🔍</button></code></pre>
<p>XPath:</p>
<pre><code>//button[@aria-label='Search']</code></pre>
<hr>
<h2>93. XPath for Angular Form Controls</h2>
<p>Angular applications may expose attributes such as <code>formcontrolname</code>.</p>
<pre><code>//input[@formcontrolname='email']</code></pre>
<hr>
<h2>94. XPath for React Applications</h2>
<p>React applications may contain dynamically generated class names. Stable attributes such as <code>data-testid</code>, <code>aria-label</code>, or application-specific attributes can sometimes provide more maintainable XPath expressions.</p>
<pre><code>//button[@data-testid='login-button']</code></pre>
<hr>
<h2>95. XPath for Specific Table Row</h2>
<p>Suppose the table contains:</p>
<pre><code>John
Smith
[email protected]
Active</code></pre>
<p>A row containing the email can be located using:</p>
<pre><code>//table[@id='users']//tr[td[contains(text(),'[email protected]')]]</code></pre>
<hr>
<h2>96. XPath for Action Button in Specific Row</h2>
<pre><code>//table[@id='users']//tr[td[contains(text(),'[email protected]')]]//button[contains(text(),'Edit')]</code></pre>
<p>This technique is useful when every row contains similar Edit or Delete buttons.</p>
<hr>
<h2>97. XPath Using Dot for Current Context</h2>
<p>The dot <code>.</code> represents the current context node in XPath expressions.</p>
<pre><code>//div[contains(@class,'product')][.//h3[text()='Laptop']]</code></pre>
<p>Here the dot refers to the current product element while checking its descendant heading.</p>
<hr>
<h2>98. XPath Using Descendant Text</h2>
<pre><code>//div[.//span[normalize-space()='Laptop']]</code></pre>
<p>This locates a div containing a descendant span with the specified text.</p>
<hr>
<h2>99. XPath with contains() and Multiple Conditions</h2>
<pre><code>//div[contains(@class,'product') and .//h3[contains(text(),'Laptop')]]</code></pre>
<hr>
<h2>100. XPath for Nested Buttons</h2>
<pre><code>//div[@class='card']//div[@class='actions']//button</code></pre>
<hr>
<h2>101. XPath for Parent Based on Child</h2>
<p>Sometimes an element can be identified through a unique child.</p>
<pre><code>//div[.//input[@name='username']]</code></pre>
<p>This selects a div containing the username input.</p>
<hr>
<h2>102. XPath for Ancestor Based on Child</h2>
<pre><code>//input[@name='username']/ancestor::form</code></pre>
<p>This locates the form containing the username field.</p>
<hr>
<h2>103. XPath for Sibling-Based Location</h2>
<pre><code>//label[normalize-space()='Password']/following-sibling::input</code></pre>
<p>This is useful when the label text is stable but the input does not have a useful unique attribute.</p>
<hr>
<h2>104. XPath with following-sibling and Index</h2>
<pre><code>//label[normalize-space()='Username']/following-sibling::input[1]</code></pre>
<hr>
<h2>105. XPath for Elements Based on Parent Attributes</h2>
<pre><code>//div[@id='loginForm']//input[@name='username']</code></pre>
<p>This restricts the search to a particular parent container.</p>
<hr>
<h2>106. XPath for Multiple Forms</h2>
<pre><code>//form[@id='loginForm']//input[@name='username']</code></pre>
<p>This is safer than using a generic selector such as:</p>
<pre><code>//input[@name='username']</code></pre>
<p>when multiple username fields may exist on the page.</p>
<hr>
<h2>107. XPath with Position in a Parent</h2>
<pre><code>//ul[@id='menu']/li[2]</code></pre>
<p>This selects the second direct <code>li</code> child.</p>
<hr>
<h2>108. XPath for First Matching Element</h2>
<pre><code>(//button[contains(@class,'submit')])[1]</code></pre>
<hr>
<h2>109. XPath for Last Matching Element</h2>
<pre><code>(//button[contains(@class,'submit')])[last()]</code></pre>
<hr>
<h2>110. XPath with not() for Exclusion</h2>
<pre><code>//button[not(@disabled)]</code></pre>
<p>This identifies buttons that do not contain a disabled attribute.</p>
<hr>
<h2>111. XPath and findElement()</h2>
<pre><code>WebElement username = driver.findElement(
By.xpath("//input[@name='username']")
);
username.sendKeys("admin");</code></pre>
<hr>
<h2>112. XPath and findElements()</h2>
<pre><code>List<WebElement> buttons = driver.findElements(
By.xpath("//button")
);
for (WebElement button : buttons) {
System.out.println(button.getText());
}</code></pre>
<hr>
<h2>113. XPath and Page Object Model</h2>
<p>XPath locators can be stored inside Page Object classes for better organization and maintainability.</p>
<pre><code>public class LoginPage {
private WebDriver driver;
private By username =
By.xpath("//input[@name='username']");
private By password =
By.xpath("//input[@name='password']");
private By loginButton =
By.xpath("//button[@type='submit']");
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void login(String user, String pass) {
driver.findElement(username).sendKeys(user);
driver.findElement(password).sendKeys(pass);
driver.findElement(loginButton).click();
}
}</code></pre>
<hr>
<h2>114. Reusable XPath Utility</h2>
<pre><code>public WebElement findByXPath(String xpath) {
return driver.findElement(
By.xpath(xpath)
);
}</code></pre>
<p>Usage:</p>
<pre><code>findByXPath("//input[@name='username']")
.sendKeys("admin");</code></pre>
<hr>
<h2>115. Reusable XPath Click Method</h2>
<pre><code>public void clickByXPath(String xpath) {
driver.findElement(
By.xpath(xpath)
).click();
}</code></pre>
<hr>
<h2>116. Reusable XPath Type Method</h2>
<pre><code>public void typeByXPath(String xpath, String text) {
driver.findElement(
By.xpath(xpath)
).sendKeys(text);
}</code></pre>
<hr>
<h2>117. XPath with TestNG</h2>
<pre><code>import org.testng.Assert;
import org.testng.annotations.Test;
@Test
public void verifyLoginButton() {
WebElement button = driver.findElement(
By.xpath("//button[@type='submit']")
);
Assert.assertTrue(button.isDisplayed());
}</code></pre>
<hr>
<h2>118. XPath Validation Example</h2>
<pre><code>WebElement message = driver.findElement(
By.xpath("//div[contains(@class,'success-message')]")
);
Assert.assertTrue(message.isDisplayed());</code></pre>
<hr>
<h2>119. XPath and NoSuchElementException</h2>
<p>If Selenium cannot find an element using the supplied XPath, <code>NoSuchElementException</code> may occur.</p>
<p>Common reasons include:</p>
<ul>
<li>Incorrect XPath syntax.</li>
<li>Wrong attribute value.</li>
<li>Element is not present.</li>
<li>Element has not loaded yet.</li>
<li>Wrong iframe context.</li>
<li>Incorrect page or URL.</li>
<li>DOM changed after navigation.</li>
</ul>
<hr>
<h2>120. XPath and InvalidSelectorException</h2>
<p>If the XPath expression is syntactically invalid, Selenium may throw an <code>InvalidSelectorException</code>.</p>
<p>Example of a valid XPath:</p>
<pre><code>//input[@id='username']</code></pre>
<p>Always verify complex XPath expressions in browser developer tools before adding them to automation code.</p>
<hr>
<h2>121. XPath and StaleElementReferenceException</h2>
<p>A previously located element can become stale if the page refreshes or the DOM element is replaced.</p>
<p>A common solution is to locate the element again rather than continuing to use an outdated WebElement reference.</p>
<hr>
<h2>122. XPath and ElementClickInterceptedException</h2>
<p>If another element overlays the target, Selenium may not be able to click it even when the XPath is correct.</p>
<p>Possible solutions include:</p>
<ul>
<li>Wait for the overlay to disappear.</li>
<li>Wait until the target becomes clickable.</li>
<li>Scroll appropriately.</li>
<li>Handle popups or modal windows.</li>
</ul>
<hr>
<h2>123. XPath with iframe</h2>
<p>If an element is inside an iframe, Selenium must first switch into the iframe.</p>
<pre><code>driver.switchTo().frame("loginFrame");
driver.findElement(
By.xpath("//input[@name='username']")
).sendKeys("admin");
driver.switchTo().defaultContent();</code></pre>
<hr>
<h2>124. XPath with Nested iframe</h2>
<pre><code>driver.switchTo().frame("outerFrame");
driver.switchTo().frame("innerFrame");
driver.findElement(
By.xpath("//input[@id='username']")
).sendKeys("admin");
driver.switchTo().defaultContent();</code></pre>
<hr>
<h2>125. XPath and Shadow DOM</h2>
<p>XPath does not automatically cross a Shadow DOM boundary. If the target element exists inside a shadow root, Selenium must first access the shadow root and then locate the element within that context using supported Shadow DOM APIs.</p>
<hr>
<h2>126. XPath and SVG Elements</h2>
<p>SVG elements can require special attention because their namespace and DOM structure can differ from ordinary HTML elements.</p>
<p>For example:</p>
<pre><code>//*[name()='svg']</code></pre>
<p>For a specific SVG element, inspect the actual DOM structure and create a locator based on stable attributes.</p>
<hr>
<h2>127. XPath vs CSS Selector</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Feature</th><th>XPath</th><th>CSS Selector</th></tr>
<tr><td>Method</td><td>By.xpath()</td><td>By.cssSelector()</td></tr>
<tr><td>ID matching</td><td>Supported</td><td>Supported</td></tr>
<tr><td>Class matching</td><td>Supported</td><td>Supported</td></tr>
<tr><td>Attribute matching</td><td>Supported</td><td>Supported</td></tr>
<tr><td>Text matching</td><td>Strong</td><td>More limited</td></tr>
<tr><td>Parent navigation</td><td>Strong</td><td>Different model</td></tr>
<tr><td>Sibling navigation</td><td>Strong</td><td>Supported</td></tr>
<tr><td>Complex DOM relationships</td><td>Highly expressive</td><td>Expressive but different</td></tr>
<tr><td>Partial attribute matching</td><td>contains(), starts-with()</td><td>*, ^=, $=</td></tr>
</table>
<hr>
<h2>128. XPath vs ID Locator</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Feature</th><th>ID</th><th>XPath</th></tr>
<tr><td>Method</td><td>By.id()</td><td>By.xpath()</td></tr>
<tr><td>Syntax</td><td>Simple</td><td>More expressive</td></tr>
<tr><td>Attributes</td><td>ID only</td><td>Multiple attributes</td></tr>
<tr><td>Relationships</td><td>No</td><td>Yes</td></tr>
<tr><td>Text</td><td>No</td><td>Yes</td></tr>
</table>
<hr>
<h2>129. XPath Best Practices</h2>
<ul>
<li>Prefer relative XPath over unnecessarily long absolute XPath.</li>
<li>Use stable attributes whenever possible.</li>
<li>Prefer unique and meaningful attributes.</li>
<li>Use <code>data-testid</code> or similar test attributes when intentionally provided by the application.</li>
<li>Use <code>contains()</code> for stable portions of dynamic attributes.</li>
<li>Use <code>starts-with()</code> when the beginning of an attribute is stable.</li>
<li>Use <code>normalize-space()</code> when whitespace can vary.</li>
<li>Avoid unnecessary indexes.</li>
<li>Avoid very long DOM paths.</li>
<li>Avoid depending on dynamically generated values unless there is a stable pattern.</li>
<li>Use explicit waits for dynamically loaded elements.</li>
<li>Store XPath locators in Page Object classes.</li>
<li>Validate complex XPath expressions before using them in tests.</li>
</ul>
<hr>
<h2>130. Avoid Fragile Absolute XPath</h2>
<p>Avoid locators such as:</p>
<pre><code>/html/body/div[2]/div[1]/form/div[3]/input</code></pre>
<p>A more maintainable locator may be:</p>
<pre><code>//form[@id='loginForm']//input[@name='username']</code></pre>
<hr>
<h2>131. Avoid Unnecessary Indexes</h2>
<p>Instead of:</p>
<pre><code>(//button)[7]</code></pre>
<p>Prefer a stable locator:</p>
<pre><code>//button[@type='submit' and normalize-space()='Login']</code></pre>
<p>Indexes can be useful when the DOM genuinely requires positional selection, but they should not be the first choice when a stable attribute is available.</p>
<hr>
<h2>132. Validate XPath in Browser Developer Tools</h2>
<p>Browsers provide developer tools that can be used to inspect the DOM and test XPath expressions.</p>
<pre><code>Open Web Page
↓
Right Click Element
↓
Select Inspect
↓
Understand DOM Structure
↓
Identify Stable Attributes
↓
Create XPath
↓
Test XPath
↓
Use XPath in Selenium
↓
Validate Automation</code></pre>
<hr>
<h2>133. Testing XPath in Browser Console</h2>
<p>XPath can be tested in browser developer tools using <code>document.evaluate()</code>.</p>
<pre><code>document.evaluate(
"//input[@id='username']",
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;</code></pre>
<p>This helps verify whether an XPath identifies the intended element before implementing it in Selenium.</p>
<hr>
<h2>134. Practical Project: Login Automation</h2>
<pre><code>driver.get("https://example.com/login");
driver.findElement(
By.xpath("//input[@name='username']")
).sendKeys("admin");
driver.findElement(
By.xpath("//input[@name='password']")
).sendKeys("admin123");
driver.findElement(
By.xpath("//button[@type='submit']")
).click();</code></pre>
<hr>
<h2>135. Practical Project: Registration Automation</h2>
<pre><code>driver.findElement(
By.xpath("//input[@name='firstName']")
).sendKeys("John");
driver.findElement(
By.xpath("//input[@name='lastName']")
).sendKeys("Smith");
driver.findElement(
By.xpath("//input[@name='email']")
).sendKeys("[email protected]");
driver.findElement(
By.xpath("//input[@name='password']")
).sendKeys("Password123");
driver.findElement(
By.xpath("//button[contains(normalize-space(),'Register')]")
).click();</code></pre>
<hr>
<h2>136. Practical Project: E-Commerce Product Selection</h2>
<pre><code>driver.findElement(
By.xpath("//h3[normalize-space()='Laptop']")
);
driver.findElement(
By.xpath("//div[contains(@class,'product-card')][.//h3[normalize-space()='Laptop']]//button[contains(normalize-space(),'Add to Cart')]")
).click();</code></pre>
<hr>
<h2>137. Practical Project: Table Data Extraction</h2>
<pre><code>List<WebElement> rows = driver.findElements(
By.xpath("//table[@id='users']//tbody//tr")
);
for (WebElement row : rows) {
System.out.println(row.getText());
}</code></pre>
<hr>
<h2>138. Practical Project: Table Row Action</h2>
<pre><code>WebElement editButton = driver.findElement(
By.xpath(
"//table[@id='users']//tr[td[normalize-space()='[email protected]']]//button[contains(normalize-space(),'Edit')]"
)
);
editButton.click();</code></pre>
<hr>
<h2>139. Practical Project: Navigation Automation</h2>
<pre><code>driver.findElement(
By.xpath("//nav//a[normalize-space()='Courses']")
).click();</code></pre>
<hr>
<h2>140. Practical Project: Checkbox Selection</h2>
<pre><code>WebElement terms = driver.findElement(
By.xpath("//input[@type='checkbox' and @name='terms']")
);
if (!terms.isSelected()) {
terms.click();
}</code></pre>
<hr>
<h2>141. Practical Project: Radio Button Selection</h2>
<pre><code>WebElement male = driver.findElement(
By.xpath("//input[@type='radio' and @value='male']")
);
if (!male.isSelected()) {
male.click();
}</code></pre>
<hr>
<h2>142. Practical Project: Dropdown Option</h2>
<pre><code>driver.findElement(
By.xpath("//select[@id='country']")
);
driver.findElement(
By.xpath("//select[@id='country']/option[@value='india']")
).click();</code></pre>
<hr>
<h2>143. XPath Automation Flow</h2>
<pre><code>Launch Browser
↓
Open Application
↓
Inspect DOM
↓
Identify Stable Attributes
↓
Create XPath
↓
Validate XPath
↓
Use By.xpath()
↓
Locate WebElement
↓
Perform Action
↓
Validate Result
↓
Continue Test
↓
Close Browser</code></pre>
<hr>
<h2>144. XPath Quick Reference</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Requirement</th><th>XPath</th></tr>
<tr><td>ID</td><td>//input[@id='username']</td></tr>
<tr><td>Name</td><td>//input[@name='username']</td></tr>
<tr><td>Class</td><td>//button[@class='login-button']</td></tr>
<tr><td>Attribute</td><td>//input[@type='text']</td></tr>
<tr><td>Multiple Attributes</td><td>//input[@type='text' and @name='username']</td></tr>
<tr><td>Exact Text</td><td>//button[text()='Login']</td></tr>
<tr><td>Partial Text</td><td>//button[contains(text(),'Login')]</td></tr>
<tr><td>Contains Attribute</td><td>//input[contains(@id,'user')]</td></tr>
<tr><td>Starts With</td><td>//input[starts-with(@id,'user_')]</td></tr>
<tr><td>Normalized Text</td><td>//button[normalize-space()='Login']</td></tr>
<tr><td>Parent</td><td>//input[@id='username']/parent::div</td></tr>
<tr><td>Child</td><td>//div[@id='login']/child::input</td></tr>
<tr><td>Descendant</td><td>//div[@id='login']//input</td></tr>
<tr><td>Ancestor</td><td>//input[@id='username']/ancestor::form</td></tr>
<tr><td>Following Sibling</td><td>//label/following-sibling::input</td></tr>
<tr><td>Preceding Sibling</td><td>//input/preceding-sibling::label</td></tr>
<tr><td>First Match</td><td>(//button)[1]</td></tr>
<tr><td>Last Match</td><td>(//button)[last()]</td></tr>
<tr><td>Not</td><td>//input[not(@type='hidden')]</td></tr>
</table>
<hr>
<h2>145. XPath Interview Questions</h2>
<h3>Q1. What is XPath?</h3>
<p>XPath is a language used to navigate XML and HTML DOM structures and identify specific nodes. Selenium uses XPath expressions to locate web elements.</p>
<h3>Q2. What is the difference between absolute and relative XPath?</h3>
<p>Absolute XPath starts from the root and describes the complete path, while relative XPath generally starts with <code>//</code> and identifies elements using attributes, text, relationships, or other conditions.</p>
<h3>Q3. Which Selenium method is used for XPath?</h3>
<pre><code>By.xpath()</code></pre>
<h3>Q4. How do you locate an element by ID using XPath?</h3>
<pre><code>driver.findElement(
By.xpath("//input[@id='username']")
);</code></pre>
<h3>Q5. How do you locate an element using text?</h3>
<pre><code>driver.findElement(
By.xpath("//button[text()='Login']")
);</code></pre>
<h3>Q6. How do you locate an element using partial text?</h3>
<pre><code>driver.findElement(
By.xpath("//button[contains(text(),'Login')]")
);</code></pre>
<h3>Q7. What is contains() used for?</h3>
<p><code>contains()</code> is used to match a substring within an attribute value or text.</p>
<h3>Q8. What is starts-with() used for?</h3>
<p><code>starts-with()</code> identifies elements whose selected attribute or text starts with a specified value.</p>
<h3>Q9. What is normalize-space()?</h3>
<p>It normalizes whitespace and is useful when text contains unwanted leading, trailing, or repeated spaces.</p>
<h3>Q10. How do you select a parent element?</h3>
<pre><code>//input[@id='username']/parent::div</code></pre>
<h3>Q11. How do you select a child element?</h3>
<pre><code>//div[@id='login']/child::input</code></pre>
<h3>Q12. How do you select a sibling?</h3>
<pre><code>//label/following-sibling::input</code></pre>
<h3>Q13. How do you select the last matching element?</h3>
<pre><code>(//button)[last()]</code></pre>
<h3>Q14. How do you handle dynamic IDs?</h3>
<pre><code>//input[starts-with(@id,'user_')]</code></pre>
<h3>Q15. Can XPath be used with findElements()?</h3>
<p>Yes.</p>
<pre><code>driver.findElements(
By.xpath("//button")
);</code></pre>
<h3>Q16. Can XPath locate elements based on visible text?</h3>
<p>Yes. Functions such as <code>text()</code> and <code>normalize-space()</code> can be used.</p>
<h3>Q17. What is the difference between // and /?</h3>
<p>A single slash is used for a direct path step, while <code>//</code> is commonly used to search through descendants from the current context or document.</p>
<h3>Q18. Can XPath work with dynamic web pages?</h3>
<p>Yes. Functions such as <code>contains()</code>, <code>starts-with()</code>, and stable attribute combinations can help identify dynamic elements.</p>
<h3>Q19. Can XPath cross an iframe?</h3>
<p>No. Selenium must first switch into the iframe context before locating elements inside it.</p>
<h3>Q20. Can XPath automatically cross Shadow DOM boundaries?</h3>
<p>No. The appropriate shadow root context must be accessed before locating elements inside it.</p>
<hr>
<h2>146. XPath Best-Practice Checklist</h2>
<ul>
<li>Use relative XPath where appropriate.</li>
<li>Prefer stable attributes.</li>
<li>Use unique identifiers whenever available.</li>
<li>Use multiple attributes when necessary.</li>
<li>Use text-based XPath when visible text is stable.</li>
<li>Use <code>contains()</code> for stable partial values.</li>
<li>Use <code>starts-with()</code> for predictable dynamic prefixes.</li>
<li>Use <code>normalize-space()</code> when whitespace varies.</li>
<li>Avoid unnecessary indexes.</li>
<li>Avoid long absolute XPath expressions.</li>
<li>Avoid dynamically generated values when a stable attribute is available.</li>
<li>Use explicit waits for dynamic elements.</li>
<li>Switch into iframes before locating elements inside them.</li>
<li>Handle Shadow DOM through its proper context.</li>
<li>Keep XPath locators inside Page Object classes.</li>
<li>Test XPath expressions before using them in large automation suites.</li>
</ul>
<hr>
<h2>147. Final Conclusion</h2>
<p>XPath is one of the most powerful locator strategies available in Selenium WebDriver. It allows automation testers to identify elements using IDs, names, classes, attributes, visible text, partial values, indexes, parent-child relationships, sibling relationships, and advanced XPath axes.</p>
<p>A maintainable XPath should generally rely on <strong>stable attributes and meaningful relationships</strong> rather than fragile absolute DOM paths or unnecessary indexes. Functions such as <code>contains()</code>, <code>starts-with()</code>, and <code>normalize-space()</code> are especially useful when working with dynamic web applications.</p>
<p>XPath becomes even more useful when combined with Selenium concepts such as <strong>WebElement methods, explicit waits, Page Object Model, TestNG, dynamic element handling, frames, forms, tables, and real-world automation projects</strong>.</p>
<p>For structured learning of Selenium WebDriver, XPath, CSS Selectors, Web Elements, browser automation, waits, TestNG, Page Object Model, and practical automation testing, explore the <a href="https://www.justacademy.co/course-detail/selenium-training" target="_blank" rel="noopener noreferrer">JustAcademy's Selenium Training Course</a>.</p>
<p>To explore the available course demonstration and registration options, visit the <a href="https://www.justacademy.co/register-for-course-demo" target="_blank" rel="noopener noreferrer">Register for Course Demo</a> page.</p>
</div>