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)
Now that you’ve edited the question, it makes sense. Let’s consider this input:
and your non-working query:
Now,
td/text()means “select all child text nodes of all childtdnodes of current node”. In this case this will yield a node-set consisting two text nodes,xandUser Name.Now you call
normalize-space()on that node-set. The type of the sole argument ofnormalize-space()isstring?. Since a node-set is not a string, conversions kick in, per section 3.2 of XPath 1.0 recommendation:Now let’s look at the definition of string() in section 4.2:
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 callingnormalize-space('x'). Naturally, this won’t compare equal to ‘User Name’. To make this work, use:This can be transcribed as “select all
trnodes that have childtdnodes, the first childtext()node of which has a normalized string value ofUser Name” – which is what you want. Furthermore, you can simplify this to:Since a no-argument
normalize-space()will apply to the current node (which will betd), and process all text nodes within.