5

I am coding some Perl to use XPath to locate a particular td element within a table` that looks similar to this

  <table>
    <tr>
      <td>...</td>
      <td><font color="white" face="verdana, Helvetica, Arial" size="2">Showing <b>1</b>-<b>100</b> of <b>200</b> total</font></td>
      <td>...</td>
      <td>...</td>
    </tr>
  </table>

What I want is to find a td element that has a font/text() node that contains the string Showing.

matches contains(., "Showing")

A direct comparison works fine:

//td[font/text()="Showing "]

but I want to use the contains() XPath function so that the match is more flexible.

I have tried

//td[contains(font/text(), "Showing ")]

but this raises the error

XPath failed due to: A sequence of more than one item is not allowed as the first argument of contains()

and I have managed to achieve what I want with

//td[font/text()[contains(., "Showing")]]

but this is very ugly and I am hoping for something more concise. Please can someone improve on this for me, or perhaps confirm that this is the best and most concise way?

5
  • More concise? You have an xpath that says "All tds that have a font whose text contains Showing" - which is exactly your problem statement! - and you want it to be more concise?! Commented Jun 15, 2012 at 8:50
  • @AakashM: Yes I do. Just because it is one way to express what I want doesn't mean it's the cleanest. I don't have to write //td[font/text()[.="Showing "]] so I thought there may be a way using contains instead of =. Commented Jun 15, 2012 at 8:56
  • 1
    So why do you think the expression is "very ugly"? It is the one I would use -- and this means that at least to my knowledge, there isn't a more elegant one. Commented Jun 15, 2012 at 12:22
  • XPath 2.0 allows one to specify a more elegant expression that selects the same nodes. Do you want an XPath 2.0 answer? Commented Jun 15, 2012 at 12:24
  • Correction: Even in XPath 2.0 the one you are using is the most ellegant. It isn't meaningful to replace contains() with Regex, and the expression //td[some $t in font/text() satisfies contains($t, 'Showing')] compared to yours seems "stupidly verbose" to me. Commented Jun 15, 2012 at 12:43

1 Answer 1

7

Try this:

//td[contains(font/text()[1], 'Showing ')]
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Kirill. That works, but only if it is the first text node that matches. I want to find a td where any font/text() contains the given string.
@Borodin You mean like this: //td[contains(font/text(), 'Showing ')] ?
@Borodin, According to XPath spec, if an argument is not of type string, it is first converted to a string using the string() function and then the result of that conversion is evaluated. So your XPath engine doesn't work properly.
@KirillPolishchuk: Borodin is right -- the XPath expression in this answer fails to select a td where contains(font/text()[2], 'Showing') is true(), but contains(font/text()[1], 'Showing') is false()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.