开发者

how to get the normalize-space() xpath function to work?

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 :(

the data i want to find is in the following format

<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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜