Search code examples
xmlxsltxslt-1.0xslt-2.0tokenize

XSLT: How to split strings for multiple fields simultaneously


I've seen a number of posts about using tokenize() to split strings, but they all involve a single field. I have a slightly different situation and I'm not sure how to approach it.

My XML can resemble something like this:

<somefield>
    <code>A,B,C</code>
    <description>Description of A; Description of B; Description of C</description>
</somefield>

I want to transform that into something like this:

{
  "somefield": [
    {
      "code": "A",
      "description": "Description of A"
    },
    {
      "code": "B",
      "description": "Description of B"
    },
    {
      "code": "C",
      "description": "Description of C"
    }
  ]
}

I don't quite see how to split both fields simultaneously like that. Any ideas?


Solution

  • In XSLT 2.0 you could do something like

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/somefield">
        <array key="somefield">
            <xsl:variable name="descr" select="tokenize(description, ';')"/>
            <xsl:for-each select="tokenize(code, ',')">
                <xsl:variable name="i" select="position()"/>
                <map>
                    <string key="code">
                        <xsl:value-of select="."/>
                    </string>
                    <string key="description">
                        <xsl:value-of select="$descr[$i]"/>
                    </string>
                </map>  
            </xsl:for-each>
        </array>    
    </xsl:template>
    
    </xsl:stylesheet>
    

    to get:

    <?xml version="1.0" encoding="UTF-8"?>
    <array key="somefield">
       <map>
          <string key="code">A</string>
          <string key="description">Description of A</string>
       </map>
       <map>
          <string key="code">B</string>
          <string key="description"> Description of B</string>
       </map>
       <map>
          <string key="code">C</string>
          <string key="description"> Description of C</string>
       </map>
    </array>
    

    (Sorry, I don't have the time to adjust this to output JSON.)