I am currently trying the following xpath
//tr[normalize-space(td/text())='User Name']
to get all the tr that contains a td that contain 'User Name'
or 'User Name'
or开发者_StackOverflow ' User Name '
but its not working and I don't know what is wrong with the query :(
<tr><td>User Name</td></tr>
<tr><td>User Name</td></tr>
<tr><td> User Name </td></tr>
So what is the right format to write this xpath query?
Edit: it seem not work if the data is in the following format
<tr><td>x</td><td>User Name</td></tr>
<tr><td>x</td><td>y</td><td>User Name</td></tr>
<tr><td>x</td><td>y</td><td>z</td><td> User Name </td></tr>
so now how can i write the xpath query?
note: "//tr[normalize-space(td/text()) = 'User Name']" wont work but "//tr/td[normalize-space(text()) = 'User Name']" will work (but i want to get the tr and not the td element)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.
This works fine here:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(@"
<table>
<tr><td>User Name</td></tr>
<tr><td> User Name </td></tr>
<tr><td> User Name </td></tr>
</table>");
Console.WriteLine(
xmlDoc.SelectNodes(
"//tr[td[normalize-space(.) = 'User Name']]").Count); // shows "3"
Can you please update your question with a actual XML sample?
精彩评论