Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

xpath

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)

like image 272
Karim Avatar asked Dec 01 '09 21:12

Karim


People also ask

How do you use normalize-space to write XPath?

If an element has spaces in its text or in the value of any attribute, then to create an xpath for such an element we have to use the normalize-space function. It removes all the trailing and leading spaces from the string. It also removes every new tab or lines existing within the string.

What is normalize-space ()?

Use this function to trim the leading and trailing white spaces (blank spaces, tabs and new line characters), and converts multiple white spaces to a single blank space. Note: This function is only supported by the CDC Replication Engine for Event Server.

How do you normalize a space in Java?

normalizeSpace() is a static method of the StringUtils class which is used to return the whitespace normalized string by removing the leading and trailing whitespace and then replacing sequences of whitespace characters with a single space.


2 Answers

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.

like image 195
Pavel Minaev Avatar answered Oct 14 '22 23:10

Pavel Minaev


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?

like image 34
Rubens Farias Avatar answered Oct 14 '22 23:10

Rubens Farias