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.
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)