Ashok.N
Ashok.N

Reputation: 1391

Splitting a string based on the delimiter and moving them under new nodes using XSLT

I am using XSLT 1.0. I have the following xml input:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <groupLOB>M1 M2 M3 M4</groupLOB>
</root>

The tag <groupLOB> has the value M1 M2 M3 M4 Now I want to split the value into multiple strings and store them unde based on the delimiter 'space'i.e. ' '. My end xml should be as below:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <One>M1</One>
   <Two>M2</Two>
   <Three>M3</Three>
   <Four>M4</Four>
</root>

I tried with the following XSLT, but it's not giving me the required output, i.e. I am not sure how to move the split values under the new tags.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="text" />
   <xsl:template match="/*">
      <xsl:value-of select="translate(., ' ', '&#xA;')" />
   </xsl:template>
</xsl:stylesheet>

Anybody has any idea on how to do that?

Upvotes: 0

Views: 791

Answers (1)

Alejandro
Alejandro

Reputation: 1882

The XSLT 2.0 solution might be:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:for-each select="tokenize(groupLOB,' ')">
                <xsl:variable name="elementName">
                    <xsl:number value="position()" format="Ww"/>
                </xsl:variable>
                <xsl:element name="{$elementName}">
                    <xsl:value-of select="."/>                
                </xsl:element>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

And in XSLT 3.0

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:for-each select="tokenize(groupLOB,' ')">
                <xsl:element name="{format-integer(position(),'Ww')}">
                    <xsl:value-of select="."/>                
                </xsl:element>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Both output

<root>
   <One>M1</One>
   <Two>M2</Two>
   <Three>M3</Three>
   <Four>M4</Four>
</root>

Then in XSLT 1.0 you will need to tokenize by the means of an extension function like EXSLT tokenize() or with a recursive template (like Jeni Tennison's XSLT implementation of EXSLT tokenize). The big task is the conversion from numbers to words. Luckly we can see Saxon's open source to translate from a Java implemantation to an XSLT implemantation. This might take time but it is straightforward.

Check the English implementation shipped with Saxon at https://dev.saxonica.com/repos/archive/opensource/trunk/bj/net/sf/saxon/number/Numberer_en.java

Upvotes: 1

Related Questions