0

I'm attempting to get an a link on a webpage where I know the class name of the element, but the title on each row in a table is different.

For ex. Row A might look like <a href='/someaddress' class='constantClassName' title='AlwaysPresentText - Row <somenumberhere_oneormoredigits> - TextIKnowAheadOfTime'>Edit</a>

In Chrome devtools I've got //a[@class='constantClassName' and contains(text(),'Edit') and starts-with(@title,'Edit')] which gets me mostly there.

What I can't seem to get to work is appending ends-with(@title,'TextIKnowAheadOfTime') to work. In my use case, contains(text(),'sometext') may return more than one result so I need an exact match.

Using Java here, and would using a Java regex concatenated with my desired string be the fastest way to go, or is there an xpath query way to obtain a single result by exact match of the ends-with()?

trebleCode
  • 2,134
  • 19
  • 34

1 Answers1

2

This SO answer states, that

By default, selenium uses the "native" version of XPath that comes with the browser. You can make it use a version that comes with Selenium, written in JavaScript. This seems to implement XPath 1.0, based on glancing at the source.

The answer is old, but even by now, browsers don't support XPath-2.0. This is relevant, because fn:ends-with(...) is an XPath-2.0 function.

But you can emulate it with the following XPath-1.0 combination. Here, . is the value to be compared, and $ending is the string that the string "ends-with".

substring(., string-length(.) - string-length($ending) + 1) = $ending

Applied to your situation, the XPath-1.0 equivalent for

ends-with(@title,'TextIKnowAheadOfTime')

is

substring(@title, string-length(@title) - string-length('TextIKnowAheadOfTime') + 1) = 'TextIKnowAheadOfTime'

I guess that now you can make your expression match the nodes you want.

zx485
  • 28,498
  • 28
  • 50
  • 59
  • Thank you @zx485 this works like a charm. What does the `-` after the second `(@title)-string-length` mean in xpath land? – trebleCode Mar 13 '20 at 20:56
  • It simply means "subtract": subtract the length of the `$ending` string from the `@title` string (and finally add one, because XPath starts counting indexes at 1 and not 0). I added spaces to the answer to make it more understandable. – zx485 Mar 13 '20 at 20:58