Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

selenium xpath - how to select the last row of a table with certain content?

Tags:

selenium

xpath

I have a table like this:

<table>
  <th>
    <td>Area</td><td># of errors</td>
  </th>
  <tr><td>school</td><td>23</td></tr>
  <tr><td>student</td><td>0</td></tr>
  <tr><td>school</td><td>17</td></tr>
  <tr><td>student</td><td>0</td></tr>
</table>

How can I select the last row for the 'Schools' Area.

Until recently I used assert_text with

//table//tr//td[contains(text(),'school')]/following::td

and a value of 0, i.e. zero errors.

However, now I need to account for rows that have errors, but still look at the 'last' row - for an area - that has zero errors.
For this case, using

//table//tr//td[contains(text(),'school')]/following::td

incorrectly selects the first row that has the 23 errors.

I tried using tr[last()] -

//table//tr[last()]//td[contains(text(),'school')]/following::td[2]

but the problem is that this select the last table row - which is for students. I want the last table row that is for schools (it is actually the next to last table row from all rows).

I also tried:

//table//td[contains(text(),'school')][last()]/following::td[2]

but that didn't work (it still selects the 'first' school row).

I need to be able to account for just one school row, two school rows and more than 2 school rows so I need the expression to be dynamic enough to handle that.

like image 460
Michael Durrant Avatar asked Apr 12 '13 14:04

Michael Durrant


1 Answers

You are searching for an element that contains the text 'school', but the markup has the text 'School', XPath is case sensitive.

You can work around this by translating uppercase letters into lower case letters, this would make your XPath like so:

//td[contains(translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'school')][last()]/following::td[2]

*Note*

I didn't use the XPath2 lower-case() function because it won't work in all browsers.

*Edit*

Updated for the new markup the xpath that is case insensitive would be:

//tr[td[contains(translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'school')]][last()]/td[2]

or the more simplified version that is not case insensitive would be:

//tr[td[contains(., 'school')]][last()]/td[2]

(. is shorthand for text(), you can interchange them if you want to)

you could probably also get away with

//tr[td[.='school']][last()]/td[2]
like image 193
Ardesco Avatar answered Sep 20 '22 16:09

Ardesco