Reputation: 55
I am using XSLT 2.0 to transform XML to HTML. I am trying to split the attribute value at every 6th character.
My source XML looks like this:
<item effrg="521529577580620621623624628628631631642645" />
My current (failed XSLT) looks like this:
<xsl:analyze-string regex=".{{6}}" select="item/@effrg">
<xsl:matching-substring><xsl:value-of select="."/></xsl:matching-substring>
<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
</xsl:analyze-string>
My desired output should be:
521529 577580 620621 623624 628628 631631 642645
Am I on the right track? Can anyone help?
Upvotes: 2
Views: 947
Reputation: 1645
Since the user asked in a comment about Internet Explorer support, XSLT 2.0 might have been the wrong choice.
Here's a XSLT 1.0 solution:
<xsl:template name="splitString">
<xsl:param name="string"/>
<xsl:param name="size"/>
<xsl:choose>
<xsl:when test="string-length($string) > $size">
<xsl:variable name="rest">
<xsl:call-template name="splitString">
<xsl:with-param name="string" select="substring($string,$size + 1)"/>
<xsl:with-param name="size" select="$size"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat(substring($string,1,$size),' ',$rest)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Can be called like this:
<xsl:call-template name="splitString">
<xsl:with-param name="string" select="item/@effrg"/>
<xsl:with-param name="size">6</xsl:with-param>
</xsl:call-template>
Also with analyze-string in XSLT-2.0, actually this would've been sufficient:
<xsl:analyze-string select="item/@effrg" regex=".{{6}}">
<xsl:matching-substring><xsl:value-of select=".,''"/></xsl:matching-substring>
</xsl:analyze-string>
Upvotes: 1
Reputation: 163262
Or you could do
<xsl:for-each-group select="string-to-codepoints($in)"
group-adjacent="(position()-1) idiv 6">
<xsl:value-of select="codepoints-to-string((current-group(), 20))"/>
</xsl:for-each-group>
Upvotes: 2
Reputation: 66714
An alternative solution that uses substring()
inside of a for
expression to produce the sequence of number groups, then use string-join() with a space separator to produce the desired output:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="item">
<xsl:variable name="size" select="6"/>
<xsl:value-of select="string-join(for $i in 0 to string-length(@effrg) div $size
return substring(@effrg, $i*$size+1, $size),
' ')"/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 23637
To split the source string you provided you can use a simpler expression:
<xsl:value-of select="replace(item/@effrg, '(.{6}){7}', '$1 $2 $3 $4 $5 $6 $7')" />
in the context where you are running <xsl:analyze-string>
.
With <xsl:analyze-string>
you can get each $n
group with regex-group(n)
. You could then loop in XSLT concatenating the spaces in recursive call-templates.
But you can also loop more concisely in XPath 2.0 using for
and string-join
to obtain the desired result:
<xsl:template match="item">
<xsl:variable name="size" select="floor(string-length(@effrg) div 6)"></xsl:variable>
<xsl:analyze-string regex="(.{{6}}){{{$size}}}" select="@effrg">
<xsl:matching-substring>
<xsl:value-of select="string-join(for $group in 1 to $size return regex-group($group), ' ')"/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
Upvotes: 0