Popular Searches
Popular Course Categories
Popular Courses

Dynamic XPath

XPath in Selenium

Dynamic XPath in Selenium

Dynamic XPath is an XPath technique used in Selenium WebDriver to locate web elements whose attributes, values, IDs, classes, text, or other properties may change dynamically. Instead of depending on an entire attribute value that can change between page loads or application sessions, Dynamic XPath uses stable portions of the element, partial matching, text, relationships, or multiple conditions to create a more flexible locator.

XPath is an important part of Selenium WebDriver element location. Selenium training at JustAcademy covers locators including XPath and CSS selectors, along with WebDriver, TestNG, Page Object Model, automation frameworks, and real-time project execution. Learn More About Selenium Training.

You can also explore the demo registration page here: Register for Course Demo.


1. What is Dynamic XPath?

Dynamic XPath is a flexible XPath expression created to locate elements when one or more properties of the element are dynamic or unpredictable. A dynamic element may have an ID, class, name, value, or other attribute that changes every time the page is loaded.

For example, an application may generate an input element like:

<input id="username_12345" type="text">

On another page load, the same element may become:

<input id="username_98765" type="text">

A static XPath depending on the complete ID would not be reliable:

//input[@id='username_12345']

A Dynamic XPath can identify the stable portion of the ID:

//input[starts-with(@id,'username_')]


2. Why Dynamic XPath is Required

Modern web applications frequently generate dynamic HTML attributes. IDs and class names may contain random numbers, session values, framework-generated identifiers, or other changing information.

  • Dynamic IDs may change between executions.
  • Dynamic classes may contain generated values.
  • Element positions may change.
  • Multiple similar elements may exist on the same page.
  • AJAX applications may create elements dynamically.
  • JavaScript frameworks may modify the DOM.
  • Exact attribute matching may become unreliable.

Dynamic XPath provides techniques for identifying the stable characteristics of such elements.


3. Static XPath vs Dynamic XPath

Static XPathDynamic XPath
Uses exact attribute values.Can use stable portions of attribute values.
Can be affected by changing IDs.Can handle certain changing IDs.
Usually simple.Can use functions and relationships.
May become invalid after DOM changes.Can be more flexible when designed correctly.
Often depends on fixed values.Can depend on stable patterns.


4. Example of Static XPath

<input id="user_12345" type="text">

A static XPath could be:

//input[@id='user_12345']

If the ID changes to user_98765, the XPath fails.


5. Example of Dynamic XPath

Instead of matching the complete ID, identify the stable prefix:

//input[starts-with(@id,'user_')]

This can match:

user_12345

user_98765

user_45678


6. Dynamic XPath Syntax

A basic Dynamic XPath can be represented as:

//tagname[condition]

For an attribute:

//tagname[contains(@attribute,'stable-value')]

For text:

//tagname[contains(normalize-space(.),'stable-text')]

For multiple conditions:

//tagname[@attribute='value' and contains(@class,'stable-class')]


7. Dynamic XPath Using contains()

The contains() function is one of the most frequently used techniques for Dynamic XPath.

Syntax

//tagname[contains(@attribute,'value')]

Example

//input[contains(@id,'username')]

This can match IDs such as:

username_123

login_username_456

username_field_789


8. Dynamic XPath Using starts-with()

The starts-with() function is useful when the beginning of an attribute remains stable.

Syntax

//tagname[starts-with(@attribute,'value')]

Example

//input[starts-with(@id,'username_')]


9. contains() vs starts-with()

FunctionMeaningExample
contains()Checks whether the value occurs anywhere.contains(@id,'user')
starts-with()Checks whether the value starts with a specific string.starts-with(@id,'user_')


10. Dynamic XPath Using text()

The text() function can be used when visible text is stable.

//button[text()='Login']

For example:

<button>Login</button>


11. Dynamic XPath Using normalize-space()

normalize-space() is useful when text contains extra spaces or inconsistent whitespace.

//button[normalize-space(.)='Login']

For example, if the rendered text contains extra whitespace, normalize-space() can make the locator more reliable.


12. text() vs normalize-space()

ExpressionPurpose
text()='Login'Matches an exact text node.
normalize-space(.)='Login'Normalizes whitespace and compares the element string value.
contains(normalize-space(.),'Login')Matches text containing Login after whitespace normalization.


13. Dynamic XPath Using contains() with Text

//button[contains(normalize-space(.),'Login')]

This may match:

Login

Login Now

User Login

Login to Continue


14. Dynamic XPath Using Multiple Attributes

Sometimes one attribute is not enough to uniquely identify an element. Multiple conditions can be combined.

//input[@type='text' and contains(@id,'username')]

This requires the element to be a text input and its ID to contain username.


15. Dynamic XPath Using and

The and operator requires all specified conditions to be true.

//input[@type='email' and contains(@id,'email')]


16. Dynamic XPath Using or

The or operator allows either condition to match.

//input[@name='username' or contains(@id,'username')]

This can be useful when different versions of an application use different stable attributes.


17. Dynamic XPath Using not()

The not() function excludes elements that satisfy a particular condition.

//button[contains(@class,'btn') and not(@disabled)]

This selects buttons containing btn in their class while excluding disabled buttons.


18. Dynamic XPath Using Partial Class

Modern applications may add several classes to an element.

<button class="btn btn-primary login-button active">Login</button>

An exact class XPath such as the following may be unreliable:

//button[@class='login-button']

A partial class XPath can be:

//button[contains(@class,'login-button')]


19. Dynamic XPath for Dynamic Class Names

Suppose the application generates:

<div class="product-card-x7a82">

and later:

<div class="product-card-p9b41">

A Dynamic XPath can use the stable prefix:

//div[starts-with(@class,'product-card-')]

Another option is:

//div[contains(@class,'product-card-')]


20. Dynamic XPath for Dynamic Name Attribute

<input name="username_12345">

//input[starts-with(@name,'username_')]


21. Dynamic XPath for Dynamic Placeholder

<input placeholder="Enter Username - 12345">

//input[contains(@placeholder,'Enter Username')]


22. Dynamic XPath for Dynamic Value Attribute

<input value="User_98765">

//input[contains(@value,'User_')]


23. Dynamic XPath Using Parent

A stable parent container can be used to narrow down the search.

//div[contains(@class,'login-form')]//input[contains(@id,'username')]

This searches for a username input inside a login form.


24. Dynamic XPath Using Child

//div[contains(@class,'login-form')]/child::input[contains(@id,'username')]

The child axis selects direct children of the selected parent.


25. Dynamic XPath Using Descendant

//div[contains(@class,'login-form')]//input[contains(@id,'username')]

The descendant search can find the input even when it is nested inside another element.


26. Dynamic XPath Using Ancestor

//input[contains(@id,'username')]/ancestor::form[1]

This locates the nearest form ancestor of the username input.


27. Dynamic XPath Using Following

The following axis can locate elements appearing later in the document.

//label[normalize-space(.)='Username']/following::input[1]

This is useful when the input is not necessarily a direct sibling.


28. Dynamic XPath Using Preceding

The preceding axis can locate elements appearing earlier in the document.

//input[contains(@id,'password')]/preceding::label[1]


29. Dynamic XPath Using Following-Sibling

If the target element is a later sibling under the same parent, following-sibling can be used.

//label[normalize-space(.)='Username']/following-sibling::input[1]


30. Dynamic XPath Using Preceding-Sibling

//input[contains(@id,'username')]/preceding-sibling::label[1]


31. Dynamic XPath with Index

An index can be used when multiple elements match the same XPath.

(//input[contains(@name,'username')])[1]

The parentheses apply the position to the complete result set.


32. Dynamic XPath with last()

The last() function selects the last matching element.

(//button[contains(@class,'submit')])[last()]


33. Dynamic XPath with Position

(//button[contains(@class,'submit')])[2]

This selects the second matching button from the complete result set.


34. Dynamic XPath for Login Button

//button[contains(@class,'login') and normalize-space(.)='Login']


35. Dynamic XPath for Username Field

//input[contains(@id,'username') and @type='text']


36. Dynamic XPath for Password Field

//input[contains(@id,'password') and @type='password']


37. Dynamic XPath for Email Field

//input[contains(@placeholder,'Email') and @type='email']


38. Dynamic XPath for Submit Button

//button[contains(@class,'submit') and normalize-space(.)='Submit']


39. Dynamic XPath for Links

//a[contains(@href,'profile') and normalize-space(.)='Profile']

This can be useful when the URL contains a stable portion but its complete value may change.


40. Dynamic XPath for Dynamic href

//a[contains(@href,'products')]


41. Dynamic XPath for Images

//img[contains(@src,'product') and contains(@alt,'Laptop')]


42. Dynamic XPath for Product Cards

//div[contains(@class,'product-card') and .//h3[normalize-space(.)='Laptop']]

This identifies a product card using its stable product name.


43. Dynamic XPath for Add to Cart

//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]//button[contains(normalize-space(.),'Add to Cart')]

This is more specific than selecting the first Add to Cart button on the page.


44. Dynamic XPath for Tables

Tables often contain repeated rows, so identifying a row using stable cell content is useful.

//tr[.//td[normalize-space(.)='John']]//button[normalize-space(.)='Edit']

This identifies the row containing John and then locates its Edit button.


45. Dynamic XPath for Specific Table Row

//tr[td[normalize-space(.)='John'] and td[normalize-space(.)='Mumbai']]//button[normalize-space(.)='Edit']


46. Dynamic XPath for Forms

//form[.//label[normalize-space(.)='Email']]//input[@type='email']


47. Dynamic XPath for Search Boxes

//input[contains(@placeholder,'Search') or contains(@aria-label,'Search')]


48. Dynamic XPath Using aria-label

Accessibility attributes can sometimes provide useful stable information.

//button[contains(@aria-label,'Search')]


49. Dynamic XPath Using data-* Attributes

Applications may provide custom data attributes for testing.

<button data-testid="login-button-123">Login</button>

A Dynamic XPath can use a stable prefix when necessary:

//button[starts-with(@data-testid,'login-button-')]

If a stable test attribute value exists, however, using that stable value directly is generally simpler.


50. Dynamic XPath in Selenium Java

WebElement username = driver.findElement(

By.xpath("//input[contains(@id,'username')]")

);

username.sendKeys("admin");


51. Dynamic XPath Using starts-with() in Selenium

WebElement username = driver.findElement(

By.xpath("//input[starts-with(@id,'user_')]")

);

username.sendKeys("admin");


52. Dynamic XPath Using contains() in Selenium

WebElement loginButton = driver.findElement(

By.xpath("//button[contains(@class,'login')]")

);

loginButton.click();


53. Dynamic XPath Using Text in Selenium

WebElement submitButton = driver.findElement(

By.xpath("//button[normalize-space(.)='Submit']")

);

submitButton.click();


54. Dynamic XPath Using Multiple Conditions in Selenium

WebElement email = driver.findElement(

By.xpath("//input[@type='email' and contains(@id,'email')]")

);

email.sendKeys("[email protected]");


55. Dynamic XPath with findElements()

List<WebElement> buttons = driver.findElements(

By.xpath("//button[contains(@class,'btn')]")

);

System.out.println("Buttons found: " + buttons.size());


56. Dynamic XPath with Explicit Wait

Dynamic XPath identifies an element, but it does not automatically wait for that element to appear. Explicit waits can be used for dynamic web applications.

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement username = wait.until(

ExpectedConditions.visibilityOfElementLocated(

By.xpath("//input[contains(@id,'username')]")

)

);

username.sendKeys("admin");


57. Dynamic XPath with elementToBeClickable()

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement loginButton = wait.until(

ExpectedConditions.elementToBeClickable(

By.xpath("//button[contains(@class,'login')]")

)

);

loginButton.click();


58. Dynamic XPath with Runtime Variables

XPath can be constructed dynamically using Java variables.

String productName = "Laptop";

String xpath = "//h3[normalize-space(.)='" + productName + "']";

WebElement product = driver.findElement(By.xpath(xpath));


59. Dynamic XPath for Runtime Product

String productName = "Laptop";

String xpath = "//div[contains(@class,'product-card')][.//h3[normalize-space(.)='" + productName + "']]";

WebElement productCard = driver.findElement(By.xpath(xpath));


60. Dynamic XPath for Runtime Button Text

String buttonText = "Add to Cart";

String xpath = "//button[normalize-space(.)='" + buttonText + "']";

driver.findElement(By.xpath(xpath)).click();


61. Dynamic XPath Method in Page Object Model

public By getButtonByText(String text) {

return By.xpath("//button[normalize-space(.)='" + text + "']");

}


62. Dynamic XPath for Product Selection in POM

public By getProduct(String productName) {

return By.xpath(

"//div[contains(@class,'product-card')][.//h3[normalize-space(.)='" + productName + "']]"

);

}


63. Dynamic XPath in Page Object Model

public class LoginPage {

private WebDriver driver;

private By username = By.xpath("//input[contains(@id,'username')]");

private By password = By.xpath("//input[contains(@id,'password')]");

private By loginButton = By.xpath("//button[contains(@class,'login') and normalize-space(.)='Login']");

 

public LoginPage(WebDriver driver) {

this.driver = driver;

}

 

public void enterUsername(String value) {

driver.findElement(username).sendKeys(value);

}

 

public void enterPassword(String value) {

driver.findElement(password).sendKeys(value);

}

 

public void clickLogin() {

driver.findElement(loginButton).click();

}

}


64. Dynamic XPath in TestNG

@Test

public void loginTest() {

WebElement username = driver.findElement(

By.xpath("//input[contains(@id,'username')]")

);

WebElement password = driver.findElement(

By.xpath("//input[contains(@id,'password')]")

);

WebElement login = driver.findElement(

By.xpath("//button[contains(@class,'login')]")

);

username.sendKeys("admin");

password.sendKeys("admin123");

login.click();

}


65. Dynamic XPath for E-Commerce Application

<div class="product-card-a123">

<h3>Laptop</h3>

<button class="add-cart-456">Add to Cart</button>

</div>

A Dynamic XPath can be:

//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]//button[contains(@class,'add-cart')]


66. Dynamic XPath for Multiple Products

String productName = "Laptop";

By addToCart = By.xpath(

"//div[contains(@class,'product-card')][.//h3[normalize-space(.)='" + productName + "']]//button[contains(normalize-space(.),'Add to Cart')]"

);

driver.findElement(addToCart).click();


67. Dynamic XPath for Navigation Menu

//nav//a[contains(normalize-space(.),'Products')]


68. Dynamic XPath for Checkbox

//label[contains(normalize-space(.),'Terms')]/following::input[@type='checkbox'][1]


69. Dynamic XPath for Radio Button

//label[contains(normalize-space(.),'Male')]/following::input[@type='radio'][1]


70. Dynamic XPath for Dropdown Option

//div[contains(@class,'dropdown')]//option[normalize-space(.)='India']


71. Dynamic XPath and Browser Developer Tools

Chrome DevTools can be used to verify whether a Dynamic XPath returns the expected element.

$x("//input[contains(@id,'username')]")

The result should be checked to make sure the XPath is unique and points to the intended element.


72. How to Test XPath in Chrome DevTools

  1. Open the web application.
  2. Press F12 to open Developer Tools.
  3. Open the Console tab.
  4. Enter the XPath using the $x() function.
  5. Press Enter.
  6. Check the returned elements.
  7. Verify that the expected element is selected.
  8. If multiple elements are returned, make the XPath more specific.

$x("//button[contains(@class,'login')]")


73. Dynamic XPath and AJAX

AJAX-based applications can create or update elements after the initial page load. Dynamic XPath can help identify such elements, but synchronization is still required.

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement result = wait.until(

ExpectedConditions.visibilityOfElementLocated(

By.xpath("//div[contains(@class,'search-result')]")

)

);


74. Dynamic XPath and JavaScript Applications

JavaScript-heavy applications can dynamically modify the DOM. Locators should be based on stable information such as semantic attributes, stable text, container relationships, or dedicated test attributes.


75. Dynamic XPath and React Applications

React applications may generate changing classes or IDs. Instead of depending on generated values, identify stable attributes or relationships whenever possible.

//input[@type='email' and contains(@placeholder,'Email')]


76. Dynamic XPath and Angular Applications

Angular applications may also generate dynamic attributes and update the DOM dynamically. A locator should focus on stable information instead of generated values.

//button[contains(normalize-space(.),'Login')]


77. Dynamic XPath and Repeated Elements

Repeated components are common in product cards, tables, menus, lists, and dashboards. Instead of selecting an element only by its index, use a unique value inside its container.

//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]//button[contains(normalize-space(.),'Add to Cart')]


78. Dynamic XPath and WebElement Context

A dynamic locator can be scoped to a previously located WebElement.

WebElement product = driver.findElement(

By.xpath("//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]")

);

WebElement button = product.findElement(

By.xpath(".//button[contains(@class,'add-cart')]")

);

button.click();

The dot before the XPath is important because it makes the XPath relative to the current WebElement.


79. Dynamic XPath vs Absolute XPath

An absolute XPath may look like:

/html/body/div[1]/div[2]/form/div[1]/input

This type of locator can be fragile because changes in the DOM hierarchy can break it.

A relative Dynamic XPath can be:

//input[contains(@id,'username')]


80. Dynamic XPath vs Relative XPath

Dynamic XPath is not a separate XPath language. It is a practical approach to creating flexible XPath expressions. Relative XPath normally starts with // and can use functions, attributes, text, and relationships to handle dynamic elements.


81. Dynamic XPath Does Not Mean Complex XPath

A Dynamic XPath should not be unnecessarily complicated. The goal is to identify stable information rather than create the longest possible expression.

A simple locator such as:

//input[@data-testid='username']

is preferable to a complicated XPath if the data-testid is stable.


82. Dynamic XPath Using Stable Attributes

Before creating a complex Dynamic XPath, check whether the application provides a stable ID, name, data-testid, aria-label, or another meaningful attribute.

//input[@data-testid='username']


83. Dynamic XPath for Stable Test Attributes

Dedicated test attributes are often useful because they can remain stable even when visual styling changes.

//button[@data-testid='login-button']


84. Common Mistake: Using the Complete Dynamic ID

Suppose the ID changes between executions:

username_123456

username_984521

username_762314

A locator such as:

//input[@id='username_123456']

is fragile.

Instead:

//input[starts-with(@id,'username_')]


85. Common Mistake: Using contains() Too Broadly

The following XPath may return several elements:

//*[contains(@class,'btn')]

A more specific locator could be:

//button[contains(@class,'btn') and normalize-space(.)='Login']


86. Common Mistake: Ignoring Duplicate Matches

Always verify the number of matching elements.

List<WebElement> elements = driver.findElements(

By.xpath("//button[contains(@class,'login')]")

);

System.out.println("Matching elements: " + elements.size());


87. Common Mistake: Excessive Index Usage

A locator such as:

(//button)[5]

depends on the current order of elements. If another button is added before it, the locator may select a different element.

Prefer meaningful conditions:

//button[normalize-space(.)='Login']


88. Common Mistake: Using Following Too Broadly

The following XPath may identify an unrelated input:

//label/following::input[1]

A more specific context can be used:

//form[contains(@id,'login')]//label[normalize-space(.)='Username']/following::input[1]


89. Common Mistake: Ignoring Whitespace

Text may contain whitespace that makes exact text matching unreliable.

Instead of:

//button[text()='Login']

consider:

//button[normalize-space(.)='Login']


90. Common Mistake: Ignoring Synchronization

A correct Dynamic XPath may still fail if the element has not appeared yet.

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement element = wait.until(

ExpectedConditions.visibilityOfElementLocated(

By.xpath("//input[contains(@id,'username')]")

)

);


91. Best Practice: Prefer Stable Attributes

If a unique and stable ID is available, it should generally be preferred over a complex XPath.

//input[@id='username']


92. Best Practice: Use Dedicated Test Attributes

//input[@data-testid='username']

Dedicated test attributes can provide a stable contract between the application and automation tests.


93. Best Practice: Use Meaningful Text

//button[normalize-space(.)='Login']

Text-based locators are useful when the text is stable and unique.


94. Best Practice: Combine Conditions Carefully

//input[@type='text' and contains(@id,'username')]

Additional conditions should make the locator more specific without making it unnecessarily dependent on unstable properties.


95. Best Practice: Scope the Search

//form[contains(@class,'login-form')]//input[contains(@id,'username')]

Scoping the search to a relevant container can reduce accidental matches.


96. Best Practice: Prefer Relative XPath

Relative XPath is generally easier to maintain than a long absolute XPath.

//input[contains(@id,'username')]


97. Best Practice: Verify XPath Uniqueness

List<WebElement> matches = driver.findElements(

By.xpath("//button[normalize-space(.)='Login']")

);

if (matches.size() != 1) {

throw new RuntimeException("Login button locator is not unique.");

}


98. Best Practice: Use Explicit Waits

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement loginButton = wait.until(

ExpectedConditions.elementToBeClickable(

By.xpath("//button[contains(@class,'login')]")

)

);

loginButton.click();


99. Best Practice: Keep Locators in Page Objects

private final By loginButton =

By.xpath("//button[contains(@class,'login') and normalize-space(.)='Login']");

Centralizing locators makes maintenance easier when the application's DOM changes.


100. Best Practice: Build Reusable Dynamic Locator Methods

public By getElementByText(String text) {

return By.xpath("//*[normalize-space(.)='" + text + "']");

}


101. Dynamic XPath with Special Characters

When runtime text contains quotation marks or apostrophes, XPath string construction requires additional care.

For example:

John's Laptop

XPath concat() can be used when required.

concat('John', "'", 's Laptop')


102. Dynamic XPath Using concat()

//div[normalize-space(.)=concat('John', "'", 's Laptop')]


103. Dynamic XPath for Changing Numeric IDs

<input id="user12345">

//input[starts-with(@id,'user')]


104. Dynamic XPath for Prefix and Suffix

If the stable value is at the beginning:

//input[starts-with(@id,'input_')]

If a stable portion occurs somewhere inside:

//input[contains(@id,'_username')]


105. Dynamic XPath Function Reference

TechniqueExamplePurpose
contains()contains(@id,'user')Matches a partial attribute value.
starts-with()starts-with(@id,'user_')Matches a stable prefix.
text()text()='Login'Matches an exact text node.
normalize-space()normalize-space(.)='Login'Handles whitespace.
and@type='text' and contains(@id,'user')Requires multiple conditions.
or@name='user' or contains(@id,'user')Allows either condition.
not()not(@disabled)Excludes matching elements.
last()(//button)[last()]Selects the last result.
Position(//button)[2]Selects a specific result.
ancestor/ancestor::formMoves upward in the DOM.
following/following::inputMoves forward in document order.
preceding/preceding::labelMoves backward in document order.
following-sibling/following-sibling::inputFinds later siblings.
preceding-sibling/preceding-sibling::labelFinds earlier siblings.


106. Dynamic XPath Quick Reference

RequirementDynamic XPath
Dynamic ID prefix//input[starts-with(@id,'user_')]
Dynamic ID partial match//input[contains(@id,'username')]
Dynamic class//button[contains(@class,'login')]
Exact button text//button[normalize-space(.)='Login']
Partial button text//button[contains(normalize-space(.),'Login')]
Dynamic placeholder//input[contains(@placeholder,'Email')]
Element after label//label/following::input[1]
Element before input//input/preceding::label[1]
Product card//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]
Product button//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]//button


107. Practical Example: Dynamic Login Page

<div class="login-container-784">

<label>Username</label>

<input id="user_87364" type="text" placeholder="Enter Username">

<label>Password</label>

<input id="pass_92837" type="password" placeholder="Enter Password">

<button class="btn-login-928">Login</button>

</div>

Dynamic XPath for username:

//div[contains(@class,'login-container')]//input[starts-with(@id,'user_')]

Dynamic XPath for password:

//div[contains(@class,'login-container')]//input[starts-with(@id,'pass_')]

Dynamic XPath for login button:

//div[contains(@class,'login-container')]//button[contains(@class,'btn-login') and normalize-space(.)='Login']


108. Practical Selenium Implementation

WebDriver driver = new ChromeDriver();

driver.get("https://example.com");

WebElement username = driver.findElement(

By.xpath("//input[starts-with(@id,'user_')]")

);

WebElement password = driver.findElement(

By.xpath("//input[starts-with(@id,'pass_')]")

);

WebElement login = driver.findElement(

By.xpath("//button[contains(@class,'btn-login') and normalize-space(.)='Login']")

);

username.sendKeys("admin");

password.sendKeys("admin123");

login.click();


109. Practical Example: Dynamic E-Commerce Application

<div class="product-card-x78">

<h3>Laptop</h3>

<span>₹50,000</span>

<button class="add-cart-456">Add to Cart</button>

</div>

Dynamic XPath:

//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]//button[contains(@class,'add-cart')]


110. Practical Example: Dynamic Table

<tr>

<td>John</td>

<td>QA Engineer</td>

<td>Mumbai</td>

<td><button class="edit-123">Edit</button></td>

</tr>

Dynamic XPath:

//tr[.//td[normalize-space(.)='John'] and .//td[normalize-space(.)='Mumbai']]//button[contains(@class,'edit')]


111. Practical Example: Dynamic Search Result

//div[contains(@class,'search-result')][.//h3[contains(normalize-space(.),'Selenium')]]//a[contains(normalize-space(.),'View')]


112. Dynamic XPath and Iframes

Dynamic XPath does not automatically cross an iframe boundary. Selenium must first switch to the iframe.

WebElement frame = driver.findElement(

By.xpath("//iframe[contains(@id,'login-frame')]")

);

driver.switchTo().frame(frame);

WebElement username = driver.findElement(

By.xpath("//input[contains(@id,'username')]")

);


113. Dynamic XPath and Multiple Windows

When a new window or tab opens, Selenium must switch to the correct window before locating its elements.

for (String handle : driver.getWindowHandles()) {

driver.switchTo().window(handle);

}


114. Dynamic XPath and Shadow DOM

Shadow DOM creates a separate DOM boundary. XPath cannot simply be used from the main document to directly cross a shadow root. Selenium provides ShadowRoot-related APIs that should be used when interacting with elements inside a shadow DOM.


115. Dynamic XPath and Stale Elements

When a JavaScript application replaces an element in the DOM, a previously stored WebElement may become stale. In such situations, synchronize with the application state and locate the element again when required.


116. Dynamic XPath in Automation Frameworks

In large automation projects, Dynamic XPath should be centralized inside Page Object classes or reusable locator methods.

public By usernameField() {

return By.xpath("//input[contains(@id,'username')]");

}

public By product(String name) {

return By.xpath(

"//div[contains(@class,'product-card')][.//h3[normalize-space(.)='" + name + "']]"

);

}


117. Dynamic XPath and Maintainability

A maintainable XPath should clearly communicate what element it is locating. For example:

//div[contains(@class,'product-card')][.//h3[normalize-space(.)='Laptop']]//button[contains(normalize-space(.),'Add to Cart')]

This locator identifies the Add to Cart button associated with the Laptop product rather than simply selecting an arbitrary Add to Cart button.


118. Advantages of Dynamic XPath

  • Can handle changing IDs.
  • Can handle changing class values when stable portions exist.
  • Supports partial attribute matching.
  • Supports partial text matching.
  • Supports parent-child relationships.
  • Supports sibling relationships.
  • Supports ancestor and descendant relationships.
  • Can work with repeated UI components.
  • Can be combined with explicit waits.
  • Can reduce locator maintenance when designed correctly.


119. Limitations of Dynamic XPath

  • It may return multiple elements if the condition is too broad.
  • Changing DOM structure can still break the XPath.
  • Overly complicated XPath can be difficult to maintain.
  • Indexes can become unstable.
  • contains() can create unintended matches.
  • Dynamic XPath does not solve synchronization problems.
  • It is not always better than a stable ID or test attribute.


120. When Should You Use Dynamic XPath?

  • When an element ID changes dynamically.
  • When class values contain changing portions.
  • When a stable portion of an attribute exists.
  • When visible text is stable.
  • When an element must be located through another element.
  • When repeated components need contextual identification.
  • When parent, child, sibling, ancestor, following, or preceding relationships are useful.


121. When Should You Avoid Dynamic XPath?

  • When a stable unique ID is available.
  • When a stable data-testid or similar test attribute is available.
  • When a simpler locator is more readable and reliable.
  • When the XPath matches multiple unrelated elements.
  • When the expression depends heavily on unstable indexes.
  • When the XPath becomes unnecessarily complex.


122. Dynamic XPath Interview Questions

Q1. What is Dynamic XPath?

Answer: Dynamic XPath is an XPath expression designed to locate elements using stable portions of attributes, text, DOM relationships, or other conditions when some element properties change dynamically.

Q2. Why is Dynamic XPath used in Selenium?

Answer: It is used when exact element attributes such as IDs or classes may change and a static XPath would become unreliable.

Q3. Which functions are commonly used for Dynamic XPath?

Answer: Common techniques include contains(), starts-with(), normalize-space(), text(), concat(), not(), position(), and last().

Q4. What is the difference between contains() and starts-with()?

Answer: contains() checks whether a value occurs anywhere within a string, while starts-with() checks whether a string begins with a particular value.

Q5. How can you handle a dynamic ID?

Answer: Identify the stable portion of the ID and use contains() or starts-with().

//input[starts-with(@id,'username_')]

Q6. How can you locate a dynamic button?

Answer: Use stable portions of the class, text, aria-label, data attribute, or another reliable property.

//button[contains(@class,'login') and normalize-space(.)='Login']

Q7. How can you handle extra spaces in element text?

Answer: Use normalize-space().

//button[normalize-space(.)='Login']

Q8. Is Dynamic XPath always better than ID?

Answer: No. If a stable unique ID is available, the simpler ID locator is generally preferable.

Q9. Can Dynamic XPath handle AJAX elements?

Answer: Dynamic XPath can help locate elements whose attributes change, but explicit synchronization may still be necessary when the element is loaded asynchronously.

Q10. How do you verify a Dynamic XPath?

Answer: Test it in browser Developer Tools using the $x() function and verify that the expected element is returned.


123. Dynamic XPath Debugging Checklist

  • Inspect the actual DOM.
  • Identify which attribute values are changing.
  • Find stable portions of those values.
  • Use contains() when a stable partial value exists.
  • Use starts-with() when a stable prefix exists.
  • Use normalize-space() for inconsistent whitespace.
  • Use multiple conditions when necessary.
  • Use container-based XPath for repeated components.
  • Check whether the XPath returns one element or multiple elements.
  • Test the XPath in Chrome DevTools.
  • Check whether an iframe is involved.
  • Check whether the element is dynamically loaded.
  • Use explicit waits when required.
  • Prefer stable IDs and dedicated test attributes whenever available.
  • Keep locators centralized in Page Objects.


124. Dynamic XPath Best Practices

  1. Prefer stable attributes whenever possible.
  2. Use Dynamic XPath when attributes genuinely change.
  3. Use contains() for stable partial values.
  4. Use starts-with() for stable prefixes.
  5. Use normalize-space() for text matching.
  6. Combine conditions only when they add meaningful uniqueness.
  7. Scope searches to relevant containers.
  8. Avoid unnecessary indexes.
  9. Verify XPath uniqueness.
  10. Use explicit waits for asynchronous elements.
  11. Keep locators readable.
  12. Store locators in Page Object classes.
  13. Test locators in Developer Tools.
  14. Prefer dedicated test attributes when available.


125. Final Summary

Dynamic XPath is an important Selenium technique for locating elements whose attributes or other properties change dynamically. Instead of relying on a complete unstable value, testers can use stable portions of attributes, partial text, XPath functions, multiple conditions, and relationships between elements.

The most commonly used Dynamic XPath techniques include contains(), starts-with(), normalize-space(), text(), and, or, not(), positional predicates, and XPath axes such as ancestor, following, preceding, following-sibling, and preceding-sibling.

Dynamic XPath should not simply be made longer or more complicated. A good locator should be stable, specific, readable, maintainable, and preferably unique. If a stable ID or dedicated test attribute is available, that simpler locator should generally be preferred.

Dynamic web applications may also require synchronization. Therefore, Dynamic XPath should be combined with appropriate Selenium wait strategies when elements are loaded or updated asynchronously.

JustAcademy's Selenium training curriculum includes element location using XPath and CSS selectors, Selenium WebDriver, automation frameworks, and practical project-oriented learning. Explore Selenium Training.

For a free course demo and course-related discussion, visit Register for Course Demo.

whatsapp