# Beginner's Guide to XPath

<details>

<summary>XPath Syntax Cheat Sheet</summary>

* **/** - selects from the root node (absolute path)
* **//** - selects from the specified node (relative path)
* **element** - selects all elements with the given tag name
* **\[predicate]** - adds a condition to selection filter
* **@attribute="value"** - selects the value of the specified attribute
* **text()="value"** - selects the text within an element
* **position()="index"** - selects the element by its position among siblings

**Chaining predicates**

* //\*\[@attribute1="value"]\[@attribute2="value"]
* //\*\[@attribute1="value" and @attribute2="value"]

**Selecting position**

Both expressions below select an *img* element that is the 2nd child of *div:*

* //div/img\[position()="2"]&#x20;
* //div/img\[2]

**String vs substring search algorithms**

* //\*\[@class="className"] - searches for exact match
* //\*\[contains(@class, "className")] - searches for partial match

</details>

### Why use XPath

Knowing the basics of this versatile tool is almost a must in automated testing. Ideally, the most reliable tests are built with the use of IDs or test-IDs. In reality though there are a lot of web sites that don't utilize IDs, forcing us to use other attributes to find elements. You may also encounter cases where, as a part of your test, you need to check on certain properties of an element, like position, text content or a state of being disabled, for example. That's when XPath and CSS selectors need to be explored for writing locator expressions.&#x20;

### What is XPath

XPath, or XML Path, is a syntax expression language with its own functions and operators, that uses path expressions to select nodes or node-sets in an XML or HTML document. It is wide spread across many programming languages and testing frameworks. XPath implementations are complete in Chrome, Firefox and Edge, so XPath locators work well for cross-browser testing and can be validated right in the browser devtools.

Here's what a typical XPath selector looks like:

<figure><img src="/files/WL4cyko4DQKIXAlRuisB" alt=""><figcaption><p>This one targets a <strong>button</strong> that has a <em><strong>data-testid</strong></em> attribute with a value of "<em><strong>sign-in-btn</strong></em>".</p></figcaption></figure>

### How to use XPath

XPath selectors are really easy to use once you get to know how to construct them. To begin, let's take a look at the basic XPath syntax (parts **in bold** cannot be omitted from selector):

* **current node selector (/ or //)**
* **element (tag name)**
* \[predicate]
* @attribute ="value"
* function()="value"

<figure><img src="/files/HrWnFBDuDwVotyYOv9Ns" alt=""><figcaption><p>The most common type of a path expression in testing</p></figcaption></figure>

Not every path expression will have all of these pieces in it. The look of a selector and how specific it is often depends on the context and the goal. There's always a **slash** or a **double-slash**, **tag name** also cannot be omitted, but it can be replaced with an asterisk symbol **\***, indicating that any tag name will match.&#x20;

{% hint style="info" %}
Omitting **current node selector** is the same as using a single slash **/**.
{% endhint %}

***

### Absolute vs Relative XPath selectors

XPaths can be absolute **/** and relative **//**

* **absolute /** XPath expressions start from the root of the HTML document and specify the complete path to the targeted element. It is recommend to avoid using absolute paths as they are vulnerable to page structure changes. Furthermore such tests are harder to read and maintain.

<div data-full-width="false"><figure><img src="/files/Yu3zyA79mBzerJrszT6e" alt=""><figcaption><p>Absolute XPaths often look like this</p></figcaption></figure></div>

* **relative //** XPath expressions start from a specified element and navigate the DOM hierarchy to locate the targeted element. Such expressions are shorter, more reliable and readable. Here's an example with the same button as before, but instead of targeting it by specifying the complete path, we have located the button by specifying its **tag name** and **ID attribute**:

<figure><img src="/files/wzoOxXN0uZeN2LyBCpGG" alt=""><figcaption><p>Relative XPath of the same button as above</p></figcaption></figure>

***

### Predicates

Predicates are used to find a specific node or a node that contains a specific value. In other words they are extra conditions added to selector to make it more specific, hence more precise. Predicates are always enclosed in square brackets **\[ ]** and they cannot be used by themselves - there always have to be a **current node selector** and a **tag name**. Inside the brackets, there's usually an attribute and/or a function and a value. &#x20;

#### Here are some typical examples:

|               Path expression              |                                                          Result                                                         |
| :----------------------------------------: | :---------------------------------------------------------------------------------------------------------------------: |
|  //input\[@placeholder="Enter your Email"] | selects an *input* element, anywhere on the page, that has a *placeholder* attribute with a value of "Enter your Email" |
| //div/button\[@data-testid="save-changes"] |  selects a *button* element that is a child of a *div* and has a *data-testid* attribute with a value of "save-changes" |
|         //\*\[@for="tos-checkbox"]         |        selects an element, regardless of its tag name, that has a *for* attribute with a value of "tos-checkbox"        |

If you need to specify multiple predicates, there are two ways to go about it:

* chaining predicates separately, enclosing each one in square brackets\
  `//*[@id="accept"][@type="checkbox"]`
* using ***and*** operator inside single square brackets\
  `//*[@id="accept" and @type="checkbox"]`

***

### Selecting position

Using the DOM hierarchy position of elements to make locators more specific can be very useful in certain scenarios. There are two ways you can select an element by its position in relation to its parent element **(indexation starts from 1)**:

* using its index in separate square brackets `[2]`
* using the function `[position()="2"]`

#### Here are some examples with selectors utilizing both position and other attributes:

<table><thead><tr><th width="363" align="center">Path expression</th><th align="center">Result</th></tr></thead><tbody><tr><td align="center">//img[@alt="logo"][2]</td><td align="center">selects an <em>img</em> element that has an <em>alt</em> attribute with a value of "logo" and is the second child of an unspecified element</td></tr><tr><td align="center">//tr/td[position()="3" and text()="Savings"]</td><td align="center">selects a <em>td</em> element that has inner text "Savings" and is the third child of the <em>tr</em> element</td></tr></tbody></table>

{% hint style="danger" %}
Keep in mind that using the index with ***and*** operator in the same brackets will produce a faulty selector, e.g.,`//*[2 and @attribute]`
{% endhint %}

***

### Functions

There are more than 200+ functions in XPath, catering to various usage scenarios. Due to the fact that we don't need most of them in automated testing, we are only talking here about the most useful XPath functions in everyday testing routine.&#x20;

Like in many high-level programming languages, calling a function in an XPath expression involves round brackets **()**:

<figure><img src="/files/Lt3YT9srXyyd4kw1qlmI" alt=""><figcaption></figcaption></figure>

#### Here's a shortlist of the most useful XPath functions in testing:

<table><thead><tr><th width="143">Function</th><th width="308">Description</th><th>Example</th></tr></thead><tbody><tr><td>text()</td><td>returns the text content of element</td><td>//button[text()="Execute"]</td></tr><tr><td>position()</td><td>returns the XPath index of element</td><td>//a[position()="2"]</td></tr><tr><td>last()</td><td>returns the highest index of an element among its siblings </td><td>//a[last()]</td></tr><tr><td>contains()</td><td>searches for a substring anywhere in the value</td><td>//*[contains(@class, "btn-primary")]</td></tr><tr><td>starts-with()</td><td>searches for a substring at the start of the value</td><td>//*[starts-with(text(), "Hello, Wor")]</td></tr><tr><td>ends-with()</td><td>searches for a substring at the end of the value</td><td>//*[ends-with(text(), "llo, World!")]</td></tr></tbody></table>

{% hint style="info" %}
Please, keep in mind that all functions are **case-sensitive** when matching values.
{% endhint %}

One function stands out in particular. **Text()** allows us to find an element by its text node aka inner text. This is a powerful tool that only XPath provides. It is particularly useful when a targeted element does not have enough attributes or unique attribute values.

<figure><img src="/files/qbosYPpzt8xVdO1gKsfs" alt=""><figcaption><p>Will match any element with the specified inner text</p></figcaption></figure>

Another common function is **contains()**, it is used for substring searches. Let's say we only want to select a certain significant part of this text value. To do that we can use the **text()** and the substring we are looking for as the arguments for the **contains()** function.

<figure><img src="/files/isH9ZlHHjqu9MnsmRSvQ" alt=""><figcaption><p>Will match the same element as above</p></figcaption></figure>

**last()** returns the highest index of an element among its siblings, a numeric value, hence it can be used as is. The expression in the figure below selects a *button* element that is the last child of a *container* element.

<div data-full-width="false"><figure><img src="/files/Cv4Xog0bRRwF2bTWEiXQ" alt=""><figcaption></figcaption></figure></div>

***

### Using selectors as checks

All these tools make up for a very robust and powerful selector constructor. Apart from locating elements to interact with, XPath expressions can be used as checks and often serve as test result verification steps.

Let's take a look at this simple test of a Terms and Services checkbox. In the test we are clicking on the checkbox and want to make sure that it has been checked as a result.

<figure><img src="/files/WyM4Tvzc14U6Y0AdyYDW" alt=""><figcaption></figcaption></figure>

The expression in Step 2 finds the checkbox element by specifying its ancestor and ID attribute. Step 4 is a verification step - after the checkbox has been clicked on, it verifies that it now has the **@checked** attribute.

Now that we have talked about *how* to use XPath, we can go ahead and discuss *when* to use it. Please, check out the [Use Cases](https://docs.dogq.io/use-cases) where we are looking into the most common scenarios.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dogq.io/documentation/selectors/beginners-guide-to-xpath.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
