Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

c# - 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 ' 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)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...