2

Given the following html:

<span class="fum foe"> <b>45</b> results </span>

...can anyone tell me why the following xpath is not finding it?

//span[contains(text(), "results")]

I've attempted some "normalize-space" mojo, but haven't been able to get anything to work. Went with a "fum foe" workaround but trying to understand what I'm not understanding.

Many thanks in advance!

  • Advice to newcomers: If an answer solves your problem, please accept it by clicking the large check mark (✓) next to it and optionally also up-vote it (up-voting requires at least 15 reputation points). If you found other answers helpful, please up-vote them. Accepting and up-voting helps future readers. Please see [the relevant help-center article](https://stackoverflow.com/help/someone-answers) – Gilles Quenot Jul 02 '20 at 00:11

2 Answers2

1

This doesn't match because of the 'b' tag.

This one works:

//span[contains(., "results")]

. is a multiple node text search.

Learn about the dot.

And the explanation by one of XPath dad, thanks Mr Kay

Gilles Quenot
  • 154,891
  • 35
  • 213
  • 206
  • Thanks very much! I had a feeling it was something along those lines. I'm still trying to understand the logic behind this, so any pointers you have towards tutorials / manual entries which might help with that would be very much appreciated. For now, I'll investigate recursive text searches & hopefully that will help put me on the path to clarity. – Jason Witherspoon Jul 01 '20 at 21:34
  • Added link to explain the `.` – Gilles Quenot Jul 01 '20 at 22:44
1

In XPath 1.0, when a function like contains() expects a string as its first argument, and you supply a node-set containing multiple nodes (text() in your example), the node-set is converted to a string by ignoring all nodes except the first.

This elephant trap was removed in XPath 2.0, which makes this situation an error. In both versions, you can test whether any of the text nodes contains "results" using

//span[text()[contains(., "results")]]

But you would probably be quite happy to select the element if the word "contains" is split across multiple text nodes, in which case the correct query (again, in both versions) is

//span[contains(., "results")]

Use of text() in XPath expressions is very often a code smell.

Michael Kay
  • 147,186
  • 10
  • 83
  • 148