There is no i
in xpath is not entirely true. You can still use the count()
to find the index.
Consider the following page
<html>
<head>
<title>HTML Sample table</title>
</head>
<style>
table, td, th {
border: 1px solid black;
font-size: 15px;
font-family: Trebuchet MS, sans-serif;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
text-align: left;
padding: 8px;
}
tr:nth-child(even){background-color: #f2f2f2}
th {
background-color: #4CAF50;
color: white;
}
</style>
<body>
<table>
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
<th>Heading 3</th>
<th>Heading 4</th>
<th>Heading 5</th>
<th>Heading 6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data row 1 col 1</td>
<td>Data row 1 col 2</td>
<td>Data row 1 col 3</td>
<td>Data row 1 col 4</td>
<td>Data row 1 col 5</td>
<td>Data row 1 col 6</td>
</tr>
<tr>
<td>Data row 2 col 1</td>
<td>Data row 2 col 2</td>
<td>Data row 2 col 3</td>
<td>Data row 2 col 4</td>
<td>Data row 2 col 5</td>
<td>Data row 2 col 6</td>
</tr>
<tr>
<td>Data row 3 col 1</td>
<td>Data row 3 col 2</td>
<td>Data row 3 col 3</td>
<td>Data row 3 col 4</td>
<td>Data row 3 col 5</td>
<td>Data row 3 col 6</td>
</tr>
<tr>
<td>Data row 4 col 1</td>
<td>Data row 4 col 2</td>
<td>Data row 4 col 3</td>
<td>Data row 4 col 4</td>
<td>Data row 4 col 5</td>
<td>Data row 4 col 6</td>
</tr>
<tr>
<td>Data row 5 col 1</td>
<td>Data row 5 col 2</td>
<td>Data row 5 col 3</td>
<td>Data row 5 col 4</td>
<td>Data row 5 col 5</td>
<td>Data row 5 col 6</td>
</tr>
<tr>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
</tr>
</tbody>
</table>
</br>
<table>
<thead>
<tr>
<th>Heading 7</th>
<th>Heading 8</th>
<th>Heading 9</th>
<th>Heading 10</th>
<th>Heading 11</th>
<th>Heading 12</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data row 1 col 1</td>
<td>Data row 1 col 2</td>
<td>Data row 1 col 3</td>
<td>Data row 1 col 4</td>
<td>Data row 1 col 5</td>
<td>Data row 1 col 6</td>
</tr>
<tr>
<td>Data row 2 col 1</td>
<td>Data row 2 col 2</td>
<td>Data row 2 col 3</td>
<td>Data row 2 col 4</td>
<td>Data row 2 col 5</td>
<td>Data row 2 col 6</td>
</tr>
<tr>
<td>Data row 3 col 1</td>
<td>Data row 3 col 2</td>
<td>Data row 3 col 3</td>
<td>Data row 3 col 4</td>
<td>Data row 3 col 5</td>
<td>Data row 3 col 6</td>
</tr>
<tr>
<td>Data row 4 col 1</td>
<td>Data row 4 col 2</td>
<td>Data row 4 col 3</td>
<td>Data row 4 col 4</td>
<td>Data row 4 col 5</td>
<td>Data row 4 col 6</td>
</tr>
<tr>
<td>Data row 5 col 1</td>
<td>Data row 5 col 2</td>
<td>Data row 5 col 3</td>
<td>Data row 5 col 4</td>
<td>Data row 5 col 5</td>
<td>Data row 5 col 6</td>
</tr>
<tr>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
</tr>
</tbody>
</table>
</body>
</html>
The page has 2 tables and has 6 columns each with unique column names and 6 rows with variable data. The last row has the Modify
button in both the tables.
Assuming that the user has to select the 4th Modify
button from the first table based on the heading
Use the xpath //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button
The count()
operator comes in handy in situations like these.
Logic:
- Find the header for the
Modify
button using //th[.='Heading 4']
- Find the index of the header column using
count(//tr/th[.='Heading 4']/preceding-sibling::th)+1
Note: Index starts at 0
Get the rows for the corresponding header using //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]
Get the Modify
button from the extracted node list using //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button