XPath //div[contains(text(), 'string')] fails to select divs containing 'string'
Solution 1
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:
Solution 2
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.
Solution 3
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.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on November 30, 2020Comments
-
Admin over 3 years
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.
-
alecxe over 9 yearsplus one, very detailed explanation!
-
kjhughes over 9 yearsThe string-value link and explanation provided by @lwburk are valuable contributions and worth understanding. +1
-
undefinedman almost 6 years@alecxe you sir, are my hero! Finally I can select text like <p>Hello <strong>World</strong></p>