37

This is the HTML code:

<div>  <span></span>  Elangovan  </div>

I want to write an XPath for the div based on its contained text. I tried

//div[contains(text(),'Elangovan')]

but this is not working.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Elangovan S
  • 475
  • 1
  • 5
  • 8

3 Answers3

61

Replace text() with string():

//div[contains(string(), "Elangovan")]

Or, you can check that span's following text sibling contains the text:

//div[contains(span/following-sibling::text(), "Elangovan")] 

Also see:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
20

Alternatively to alecxe's correct answer (+1), the following slightly simpler and somewhat more idiomatic XPath will work the same way:

//div[contains(., "Elangovan")]

The reason that your original XPath with text() does not work is that text() will select all text node children of div. However, contains() expects a string in its first argument, and when given a node set of text nodes, it only uses the first one. Here, the first text node contains whitespace, not the sought after string, so the test fails. With the implicit . or the explicit string() first argument, all text node descendants are concatenated together before performing the contains() test, so the test passes.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
1

To make @kjhughes's already good answer just a little more precise, what you're really asking for is a way to look for substrings in the div's string-value:

For every type of node, there is a way of determining a string-value for a node of that type. For some types of node, the string-value is part of the node; for other types of node, the string-value is computed from the string-value of descendant nodes.

Both the context node (. or the div itself) and the set of nodes returned by text() -- or any other argument! -- are first converted to strings when passed to contains. It's just that they're converted in different ways, because one refers to a single element and the other refers to a node-set.

A single element's string-value is the concatenation of the string-values of all its text node descendants. A node-set's string-value, on the other hand, is the string-value of the node in the set that is first in document order.

So the real difference is in what you're converting to a string and how that conversion takes place.

Wayne
  • 59,728
  • 15
  • 131
  • 126
  • The string-value link and explanation provided by @lwburk are valuable contributions and worth understanding. +1 – kjhughes Nov 30 '14 at 03:19