Why does normalize-space(text()) not work with a preceding child element?
No doubt that this is extremely basic, but it just won't "click" for me, despite the research that I've done so far. Given the following two HTML examples:
<div _ngcontent-c35="" class="row facet-container ng-star-inserted"> <div _ngcontent-c35="" class="searchresult-header"> Locatie </div> </div>
<div _ngcontent-c42="" class="row facet-panel ng-star-inserted"> <div _ngcontent-c42="" class="facet-panel-header brand-pointer" data-target="#ft5" data-toggle="collapse"> <span _ngcontent-c42="" class="icon-plus ng-star-inserted" data-target="#ft5" data-toggle="collapse"> </span> Locatie </div> <div _ngcontent-c42="" class="collapse" id="ft5"> </div> </div>
Now I have the following piece of xpath:
According to other questions and websites about xpath, text() selects text nodes directly descending from the node we're searching on. Therefore, in example #1, I expect to retrieve the first child "div" element. This happens correctly: no issues there.
I expect the same result in example #2. However, this is not the case: apparently the "span" element disrupts this specific search. When I manually remove it, I succesfully retrieve the required "div" element. Why is the search disrupted? The text should still be a direct child of the div element, no matter if the span element is there or not.
TLDR: Why does the "span" element prevent me from finding the second "div" element in example #2?
As Jason had answered this is because the signature of
normalize-space() function, from the specs:
Function: string normalize-space(string?)
In XPath 1.0, whenever a string argument is needed, the language applies a type conversion by means of the
string() function. From the specs:
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.
So, the resulting node-set from the
text() node test is reduced to the first node in document order and then that node is converted to its string-value.
In this regards is when the always oversees whitespace only text nodes come to notice: your
div element has two text nodes:
<div> <div> <!-- HERE ENDS THE FIRST --><span> </span> Locatie <!-- HERE ENDS THE SECOND --></div> <div> </div> </div>
Whenever you have mixed content markup, it's better to use the string-value rather than the text nodes. Otherwise you should use this expression:
Re: [xsl] normalize-space problems with child elements, Why does normalize-space(text()) not work with a preceding child element? - html. No doubt that this is extremely basic, but it just won't "click" for me, despite the� why in following example I can use //label[text()[normalize-space() = 'some label']] or //label[normalize-space(text()) = 'some label'] to select label by text and
I guess that's because
normalize-space(text())='Locatie'] intend to check the first child text node (which is actually just an empty string) while you need to check the second one:
If you need generic XPath that will work for both cases try
Xpath cheatsheet, That's not exactly "weird", it is doing exactly what you asked for (but it isn't what you want). existence of leading and trailing white-space by wrapping the node before normalization <description> This decribes how <code>FOO</code> is supposed to work. <xsl:template match="text()[preceding-sibling::node() and not(� Stack Overflow Public questions and answers; Teams Private questions and answers for your team; Enterprise Private self-hosted questions and answers for your enterprise; Talent Hire technical talent
It may have something to do do with the white text/spaces (it's way over my pay grade...), because with this change of focus, the following expression seems to work with most (not all) xpath testers:
Get Xpath through text - Web Testing, Browser console. $x("//div"). Works in Firefox and Chrome. Xpath doesn't have the “check if part of space-separated list” operator, so this is //a/text() #=> "Go home" //a/@href #=> "index.html" //a/* #=> All a's child elements Steps of an expression are separated by / , usually used to pick child nodes. preceding- sibling� normalize-space(" abc def ") If an argument is not of the type string*,* it is first converted to a string and then evaluated. See the example below. If an argument is not of type string, it is first converted to a string using the string() function and then the result of that conversion is evaluated.
How to find element using contains in xpath, Can we get the xpath of an element through a text if it's unique. and normalize- space(text()), because the explanation may contain many relevant pieces of The current node will be converted into a text node, which is all of the child text nodes concatenated. This expression is wrong, it would not work. The normalize-space() function Another useful technique for controlling whitespace is the normalize-space() function. In our previous example, we used <xsl:preserve-space> and <xsl:strip-space> to control whitespace nodes in various elements, but we still have quite a bit of whitespace in the name attribute and the last <car> in the list.
If none of the attributes are static for a certain element, use any other element on the page that does have static attributes with the parent/child/sibling relations to locate. complex: //td[contains(normalize-space(@class), 'actualcell sajcell-row- lines By.xpath("//td[contains(lower-case(text()),'youruser')]") //to handle case� The fn:normalize-space function collapses whitespace in a string. Specifically, it performs three steps: Replaces each carriage return (#xD), line feed (#xA), and tab (#x9) character with a single space (#x20) Collapses all consecutive spaces into a single space; Removes all leading and trailing spaces
Name normalize-space() Function — Removes extra whitespace from its argument string. Synopsis string normalize-space( string? ) Inputs An optional string. If the argument is omitted, the normalize-space() function uses the … - Selection from XSLT [Book]
- Plus 1 for mentioning mixed content.