I have an XML with a text node, and I need to split this string into multiple chunks using XSLT 2.0. For example:
<tag>
<text>This is a long string 1This is a long string 2This is a long string 3This is a long string 4</text>
</tag>
The output should be:
<tag>
<text>This is a long string 1</text>
<text>This is a long string 2</text>
<text>This is a long string 3</text>
<text>This is a long string 4</text>
</tag>
Note that I deliberately set the chunk size to the length of each statement so that the example is easier to read and write, but the transformation should accept any value (it is okay for this value to be hardcoded).
This XSLT 1.0 transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pChunkSize" select="23"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text/text()" name="chunk">
<xsl:param name="pText" select="."/>
<xsl:if test="string-length($pText) >0">
<text><xsl:value-of select=
"substring($pText, 1, $pChunkSize)"/>
</text>
<xsl:call-template name="chunk">
<xsl:with-param name="pText"
select="substring($pText, $pChunkSize+1)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<tag>
<text>This is a long string 1This is a long string 2This is a long string 3This is a long string 4</text>
</tag>
produces the wanted, correct result:
<tag>
<text>
<text>This is a long string 1</text>
<text>This is a long string 2</text>
<text>This is a long string 3</text>
<text>This is a long string 4</text>
<text/>
</text>
</tag>
II. XSLT 2.0 solution (non-recursive):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pChunkSize" select="23"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text/text()">
<xsl:variable name="vtheText" select="."/>
<xsl:for-each select=
"0 to string-length() idiv $pChunkSize">
<text>
<xsl:sequence select=
"substring($vtheText, . *$pChunkSize +1, $pChunkSize) "/>
</text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>