2

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?

helderdarocha
  • 23,209
  • 4
  • 50
  • 65

4 Answers4

2

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>
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
1

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>
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
1

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>
Tobias Klevenz
  • 1,625
  • 11
  • 13
  • Great! Thanks. The XSLT 1.0 solution works for what I am doing. I was unaware that browsers are not yet using XSLT 2.0. – user3618078 May 12 '14 at 17:40
0

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>
helderdarocha
  • 23,209
  • 4
  • 50
  • 65
  • the replace function works great when i use Saxon to process the transformation. Does Internet Explore not support the replace function? – user3618078 May 09 '14 at 19:21
  • `replace` and `xs:analyze-string` are XSLT 2.0 features. I'm not aware of any XSLT 2.0 browser support, but I might be wrong. Check the links mentioned in this question. They should have up-do-date information: http://stackoverflow.com/questions/6282340/which-browsers-support-xslt-2-0-already . – helderdarocha May 09 '14 at 19:28
  • 1
    you don't really need the for loop and the string-join in the matching-substring...check my example, it's pretty close to what the Op had and works just the same – Tobias Klevenz May 12 '14 at 11:51