XSLT selects only nodes with text in the loop

I would like to select only nodes containing text nodes. But when I test the parent nodes of text (), which also contain child nodes with text return. I tried to check string-length (), but the parent nodes return a string length greater than 0.

In this scenario, I would only select

SendDate FirstName LastName Company Street City State Zip 

thanks

XML

 <BusinessLetter> <Head> <SendDate>November 29, 2005</SendDate> <Recipient> <Name Title="Mr."> <FirstName>Joshua</FirstName> <LastName>Lockwood</LastName> </Name> <Company>Lockwood &amp; Lockwood</Company> <Address> <Street>291 Broadway Ave.</Street> <City>New York</City> <State>NY</State> <Zip>10007</Zip> <Country>United States</Country> </Address> </Recipient> </Head> </BusinessLetter> 

XSL

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/"> <xsl:for-each select="//*[text()]"> <xsl:if test="text()"> <Match> <xsl:value-of select="name()"/>: <xsl:value-of select="string-length(text())"/> </Match> <br /> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> 

OUTPUT

 BusinessLetter: 2 Head: 3 SendDate: 17 Recipient: 4 Name: 5 FirstName:6 LastName:8 Company:19 Address:5 Street:17 City:8 State:2 Zip:5 Country:13 
+4
source share
3 answers

You have a problem with text nodes with only a space ...

A solution that saves white space only with text nodes (better when processing (X) HTML):

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="*[text()[normalize-space()]]"> <Match> <xsl:value-of select="concat(name(), ' : ', string-length(normalize-space()))"/> </Match> <br /> </xsl:template> </xsl:stylesheet> 

Output:

 <Match>SendDate : 17</Match> <br /> <Match>FirstName : 6</Match> <br /> <Match>LastName : 8</Match> <br /> <Match>Company : 19</Match> <br /> <Match>Street : 17</Match> <br /> <Match>City : 8</Match> <br /> <Match>State : 2</Match> <br /> <Match>Zip : 5</Match> <br /> <Match>Country : 13</Match> <br /> 
+3
source
Good question. I spent several days searching for an answer.
 <xsl:value-of select="string-length(normalize-space(text()[1]))" /> 
+2
source

This problem is caused by the fact that text nodes with a space are also considered.

Decision

Include this global (best place before any <xsl:template> ) directive :

 <xsl:strip-space elements="*"/> 

This instructs the XSLT processor to separate only node text files from just the white space of any (*) element in the XML document.

So, your fixed conversion is now :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <xsl:for-each select="//*[text()]"> <xsl:if test="text()"> <Match> <xsl:value-of select="name()"/>: <xsl:value-of select="string-length(text())"/> </Match> <br /> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> 

and when applied to the provided XML document :

 <BusinessLetter> <Head> <SendDate>November 29, 2005</SendDate> <Recipient> <Name Title="Mr."> <FirstName>Joshua</FirstName> <LastName>Lockwood</LastName> </Name> <Company>Lockwood &amp; Lockwood</Company> <Address> <Street>291 Broadway Ave.</Street> <City>New York</City> <State>NY</State> <Zip>10007</Zip> <Country>United States</Country> </Address> </Recipient> </Head> </BusinessLetter> 

required, the correct result is obtained :

 <Match>SendDate: 17 </Match><br><Match>FirstName: 6 </Match><br><Match>LastName: 8 </Match><br><Match>Company: 19 </Match><br><Match>Street: 17 </Match><br><Match>City: 8 </Match><br><Match>State: 2 </Match><br><Match>Zip: 5 </Match><br><Match>Country: 13 </Match><br> 
+2
source

Source: https://habr.com/ru/post/1335425/


All Articles