Now that you've edited the question, it makes sense. Let's consider this input:
<tr><td>x</td><td>User Name</td></tr>
and your non-working query:
//tr[normalize-space(td/text()) = 'User Name']
Now, td/text()
means "select all child text nodes of all child td
nodes of current node". In this case this will yield a node-set consisting two text nodes, x
and User Name
.
Now you call normalize-space()
on that node-set. The type of the sole argument of normalize-space()
is string?
. Since a node-set is not a string, conversions kick in, per section 3.2 of XPath 1.0 recommendation:
An argument is converted to type string as if by calling the string() function.
Now let's look at the definition of string() in section 4.2:
A node-set is converted to a string by returning the string-value of the node in the node-set that is first in document order. If the node-set is empty, an empty string is returned.
In our example, the first node "in document order" is the text node x
, so it is the one which will be used; the second node is ignored. Thus, you end up calling normalize-space('x')
. Naturally, this won't compare equal to 'User Name'. To make this work, use:
//tr[td[normalize-space(text()) = 'User Name']]
This can be transcribed as "select all tr
nodes that have child td
nodes, the first child text()
node of which has a normalized string value of User Name
" - which is what you want. Furthermore, you can simplify this to:
//tr[td[normalize-space() = 'User Name']]
Since a no-argument normalize-space()
will apply to the current node (which will be td
), and process all text nodes within.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…