0

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?

Ashok.N
  • 1,327
  • 9
  • 29
  • 64
  • 1
    If your processor supports it, you maybe able to use the `tokenize` function in EXSLT. See https://stackoverflow.com/questions/25855364/exsl-how-to-use-strtokenize. If not, you would have to use a recursive function. See https://stackoverflow.com/questions/11487704/how-to-make-xsl-tokenize-work – Tim C Apr 26 '19 at 09:58
  • 1
    That is only the first problem you have though. You still have the issue of outputing `One`, `Two`, `Three` as the element names, although that should warrant a new question should you not know how to do that. Thanks! – Tim C Apr 26 '19 at 09:59

1 Answers1

1

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

Alejandro
  • 1,882
  • 6
  • 13