XPath (XML Path Language) is a powerful query language used to select nodes from an XML or HTML document. In the context of Selenium, XPath is primarily used to locate elements in a web page. It provides a flexible way to navigate through elements and attributes in a document, even when no other locators like id
, class
, or name
are available or unique
- Selenium Features
- Selenium Installation
- Selenium Locators
- XPath Fundamentals
- CSS Selectors Methods
- Different Browsers Execution
- find_element & find_elements
- Check Enabled Status
- Check Displayed Status
- Check Selected Status
- Selenium Waits
- Send_keys Method
- Click Method
- Get Text
- Get Attribute Value
- Get Current URL
- Forward, Back, Refresh
- Take Screenshot
- Handle Browser Tabs
- Handle iframe
- Mouse Hover
- Context-Click
- Drag & Drop
- Handle Alerts
- Handle Dropdown
- Execute Javascript
- Scroll To element
- Headless Mode Execution
- Chrome Options
- Keyboard Action
XPath Fundamentals
1. XPath Expression
- An XPath expression is a string of characters used to navigate through the document’s structure (XML/HTML).
- It works by selecting nodes in the document that match the given pattern.
2. Absolute XPath
- Definition: An absolute XPath starts from the root node (i.e., the top of the HTML document) and specifies the exact path to reach the target element.
- Syntax: Starts with a single slash
/
and navigates through each element in the hierarchy. - Example: /html/body/div[1]/div[2]/input
- Pros: Simple to understand and write.
- Cons: Very brittle— if the structure of the page changes, the XPath breaks easily.
3. Relative XPath
- Definition: A relative XPath starts from anywhere in the HTML DOM structure and is much more flexible than an absolute XPath.
- Syntax: Starts with a double slash
//
to indicate searching from anywhere in the document. - Example:
//input[@id='username']
- In the above example, input is the tag name and id is an attribute of the web element.
- Pros: Flexible and more resilient to page structure changes.
- Cons: It can be slower if the XPath is too broad or inefficient.
Common XPath Methods and Functions
1. Basic Syntax
//
: Selects nodes in the document from the current node that match the selection, regardless of location./
: Selects nodes relative to the immediate current node.
2. Selecting by Attribute
- Select elements based on their attributes using the
@
symbol. - Example:
//input[@type='text']
- Finds an
<input>
element where thetype
attribute equals"text"
.
3. Selecting by Text Content
- Use
text()
to find an element based on its inner text. - Example:
//button[text()='Login']
HTML code
<button class=’cotent’>Login </button> - Selects a
<button>
element that contains the text"Login"
.
4. Partial Match Using contains()
contains()
is used when only part of the attribute value or text is known.- Example 1: Contains in Attribute :
//input[contains(@name, 'user')]
- Finds an
<input>
element where thename
the attribute contains the word"user"
. - Example 2: Contains in Text
//button[contains(text(), 'Submit')]
- Finds a
<button>
element where the visible text contains the word"Submit"
.
5. Using and
/or
- Combine multiple conditions using
and
oror
. - Example:
//input[@type='text' and @name='username']
- Finds an
<input>
element wheretype
is"text"
andname
is"username"
.
6. Selecting by Index
- XPath allows selecting specific instances of elements in a list using square brackets
[index]
. - Example:
(//input[@type='text'])[1]
- Selects the first
<input>
element of type"text"
. - Another example:
//div[@class='example-class'][2]
- Selects the second
<div>
element with class"example-class"
.
7. Parent-Child Relationship
- Parent to Child:
//div[@id='parent']/input
- Selects the
<input>
element that is a direct child of a<div>
element withid="parent"
.
- XPath supports navigating parent-child and ancestor-descendant relationships
- Descendant (grandchildren and below):
//div[@id='parent']//input
- Selects any
<input>
element that is a descendant (child, grandchild, etc.) of the<div>
withid="parent"
.
8. Selecting Parent or Ancestor Nodes
- Parent:
//input[@id='child']/parent::div
- Selects the parent
<div>
of the<input>
element withid="child"
. - Ancestor:
//input[@id='child']/ancestor::form
- Selects the ancestor
<form>
element of the<input>
withid="child"
.
9. XPath Axes
- Axes refer to the relationship between nodes. These are useful for navigating around the document.
Some common axes:
following
: Select all nodes after the current node.
//input[@id='username']/following::input[1]
- Selects the first
<input>
element after the<input>
withid="username"
. preceding
: Select all nodes before the current node.//input[@id='username']/preceding::div[1]
- Selects the first
<div>
element before the<input>
withid="username"
. following-sibling
: Selects sibling nodes that come after the current node.//input[@id='username']/following-sibling::input
- Selects the sibling
<input>
the element that follows the<input>
withid="username"
. - preceding-sibling: Select sibling nodes that come before the current node
//input[@id='password']/preceding-sibling::input
- Selects the sibling
<input>
element that precedes the<input>
withid="password"
.
XPath Examples in Selenium:
1. Selecting an element by ID using XPath
element = driver.find_element(By.XPATH, "//input[@id='username']")
2. Selecting an element by class name
element = driver.find_element(By.XPATH, "//div[@class='container']")
3. Selecting an element by text
element = driver.find_element(By.XPATH, "//button[text()='Submit']")
4. Using contains() in XPath
element = driver.find_element(By.XPATH, "//a[contains(text(), 'Login')]")
5. Selecting a parent element using XPath
element = driver.find_element(By.XPATH, "//span[@id='child']/parent::div")
Advanced XPath Concepts
1. Combining Multiple XPath Expressions
- Sometimes, you may need to combine different XPath conditions to locate elements effectively. This can be achieved using logical operators like
and
andor
. - Using
and
: Combines two conditions, and both must be true.//input[@type='text' and @name='username']
- This expression selects an
<input>
element wheretype
is"text"
andname
is"username"
. - Using
or
: Combines two conditions, where at least one must be true.//input[@type='text' or @type='password']
- This selects all
<input>
elements where thetype
is either"text"
or"password"
.
2. Working with Dynamic Elements
- In many web applications, elements may have dynamically generated attributes (e.g., auto-generated
id
orclass
values that change with each page load). You can use partial matches with thecontains()
function to locate dynamic elements in such cases. - Example with dynamic
id
://button[contains(@id, 'submit-')]
- This selects a
<button>
element where theid
contains"submit-"
, useful when the fullid
changes dynamically. - Handling Dynamic Classes:
//div[contains(@class, 'active-item')]
- Selects any
<div>
element that contains the class"active-item"
, even if the class attribute has multiple class names.
3. Handling Complex HTML Structures
- Web pages often have deeply nested HTML structures, and finding elements buried several layers deep can be challenging. XPath can be used effectively to navigate through these structures.
- Example with complex hierarchy :
//div[@class='container']//ul/li/a
- This selects any
<a>
the element that is inside an<li>
element, which is part of a<ul>
that is a descendant of a<div>
with class"container"
. - The
//
allows searching for elements within all descendants of the specified node, not just direct children. - Using
position()
: XPath also allows you to select elements based on their position in the document.(//div[@class='container']//ul/li)[2]
- This selects the second
<li>
element within the<ul>
inside a<div>
with class"container"
.
4. Working with Attributes that Don’t Have Values
- Sometimes, elements may have attributes without values, or you may need to select elements based on the presence of an attribute, regardless of its value.
- Example:
//input[@disabled]
- This selects all
<input>
elements that have thedisabled
attribute, regardless of its value.
5. Navigating Between Sibling Elements
- XPath supports navigating between sibling elements, which can be useful when dealing with repetitive structures, such as lists or tables.
- Select the next sibling element:
//div[@class='current']/following-sibling::div[1]
- This selects the first
<div>
element that is a sibling of the<div>
with class"current"
and comes immediately after it. - Select the previous sibling element:
//div[@class='current']/preceding-sibling::div[1]
- This selects the first
<div>
element that is a sibling of the<div>
with class"current"
and comes immediately before it.
XPath Best Practices
1. Use Relative XPath over Absolute XPath
- While absolute XPath can pinpoint an element based on the full path from the root node, it is highly prone to breaking when the structure of the page changes. Relative XPath, on the other hand, starts searching from anywhere in the document and is more resilient to changes.
- Avoid:
/html/body/div[2]/div[1]/form/input
- This will likely break if there’s even a slight change in the layout.
- Preferred:
//form[@id='loginForm']//input[@name='username']
2. Optimize XPath for Performance
- XPath can sometimes be slow, especially on large or complex web pages. Using efficient XPath expressions can improve performance.
- Use Direct Conditions:
//div[@class='container']//*[text()='Submit']
- Instead of searching broadly with multiple conditions, try to narrow down your search by providing direct attributes or shorter paths.
- Avoid Over-Using
//
: The//
operator searches through all descendants and can be slower. Use it only when necessary and prefer a more specific hierarchy if possible.