This is my XML:
<?xml version="1.0"?>
<foo>
<a>
first
<b>x</b>
<c>y</c>
</a>
<b>second</b>
<bar>hey</bar>
</foo>
This is my XSL:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/foo">
<xsl:apply-templates select="bar" />
</xsl:template>
<xsl:template match="bar">
[<xsl:value-of select="preceding-sibling::text()"/>]
</xsl:template>
</xsl:stylesheet>
I’m expecting this:
[first x y second]
However, it doesn’t work as expected. Simply put, I’m interested to join all texts (recursively) of all siblings of the current node.
>Solution :
The siblings which you select are not themselves text nodes, therefore you cannot use the text()
node test immediately after the preceding-sibiling::
axis. Instead, you must select text descendants of these siblings.
You probably also want to omit whitespace-only texts such as the one between the <b>
and <c>
elements:
[<xsl:for-each select="preceding-sibling::*//text()
[normalize-space(.)!='']"> <!-- filter out whitespace-only -->
<xsl:if test="position()>1">
<xsl:text> </xsl:text>
</xsl:if>
<xsl:value-of select="normalize-space(.)"/>
</xsl:for-each>]
If you want the texts separated by one space, you must insert that explicitly and remove trailing and leading whitespace with the normalize-space
function.
(XSLT 1.0)