XPath Functions Every Automation Engineer Should Know
text()
Selects elements based on their visible text.
Ex: //button[text()='Submit']
contains()
Matches partial text or attribute values
Ex: //div[contains(@class, 'error')]]
starts-with()
Checks if an attribute starts with a specific value.
Ex: //input[starts-with(@id, 'user_')]
ends-with(XPath 2.0+)
Used less in Selenium as it's not supported in 1.0 by
default.
Ex: //img[ends-with(@src, '.png')]
XPath Functions Every Automation Engineer Should Know
normalize-space()
Trims leading and trailing spaces, and replaces multiple s
with one
Ex: //span[normalize-space(text())='Login']
not()
Used for negating a condition.
Ex: //input[not(@disabled)]]
translate()
Solves casing issues like End, end, END.
//label[translate(text(),'ABCDEFGHIJKLMNOPQRSTUV
WXYZ','abcdefghijklmnopqrstuvwxyz')='username']
last()
Selects the last node in a group.
Ex: //ul/li[last()]
position()
Selects a specific position from a node set.
Ex: //div[@class='card'][position()=2]
XPath Functions Every Automation Engineer Should Know
and, or
Combine multiple conditions.
Ex: //input[@type='text' and @name='username']
name()
Returns the name of the current node.
Ex: //*[name()='svg']
ancestor::*
Selects all ancestors (parents, grandparents) of an elemen
Ex: //button[text()='Delete']/ancestor::div[@class='modal']
following-sibling::
Selects all siblings that follow the current node.
Ex: //label[text()='Email']/following-sibling::input
XPath Functions Every Automation Engineer Should Know
preceding-sibling::
Selects all siblings before the current node.
Ex: //div[@class='footer']/preceding-sibling::div[1]
self::
Refers to the context node itself.
Ex: //a[@class='active']/self::a
parent::
Selects the parent of the current node.
Ex: //span[@class='price']/parent::div
child::
Selects direct children of the node.
Ex: //ul[@id='menu']/child::li
descendant::
Selects all descendants (children, grandchildren) of node.
Ex: //div[@class='container']/descendant::input
Real-World XPath Challenges (And How to Write Smart
Locators That Don’t Break
Casing Inconsistencies (e.g., End vs end)
Challenge: Button text varies: End, END, end
Problem: text()='end' only matches exact case.
Solution: Use translate() to convert all to lowercase
before comparing.
Xpath:
//*[translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz') = 'end']
Hidden Elements Triggering Errors
Challenge: Locators match elements that aren’t visible
Problem: Selenium clicks but nothing happens
Solution: Combine XPath with visibility in code or filter
by attributes
Xpath:
//button[text()='Submit' and
not(contains(@style,'display:none'))]
Real-World XPath Challenges (And How to Write Smart
Locators That Don’t Break
Data Is in Attributes, Not Visible Text
HTML:
<img src="logo.png" alt="Company Logo">
Challenge: There’s no visible text to use
Solution: Use attribute match
Xpath: //img[@alt='Company Logo']
Text Wrapped in HTML Tags
HTML:
<p>Welcome <strong>Back</strong></p>
Challenge: Text is split across elements
Solution: Use dot (.) to match combined content
Xpath://p[contains(., 'Welcome Back')]
Real-World XPath Challenges (And How to Write Smart
Locators That Don’t Break
Dynamic IDs or Class Names
HTML:
<button id="btn_123_submit" class="btn-primary-
submit">Submit</button>
Challenge: IDs/classes change with each build (btn_123,
submit_456, etc.)
Xpath: //button[contains(@id, 'submit')]
//button[starts-with(@class, 'btn-primary')]
Dynamic Tables With No IDs
HTML:
<table><tr><td>Name</td><td>Akshaya</td></tr>
</table>
Challenge: You want to locate data under specific
headers in dynamic rows.
Solution: Use XPath axes like following-sibling,
preceding-sibling
Xpath://td[text()='Name']/following-sibling::td
How AI Is Helping in Writing XPath Locators
Auto-suggesting the Most Stable Locator
Analyze DOM patterns
Avoid brittle attributes like random IDs
Suggest the most stable and reusable XPath or CSS
locator
Natural Language to XPath
You can describe what you want like:
"Find the button with label 'Add to Cart' inside the
product tile"
AI will generate something like:
xpath
//div[contains(@class,'product')]//button[text()='Add to
Cart']