XSLT : How to translate JSON to XML

Translate Json to XML using XSLT

This is possible using XSLT 3.0 ** Payload needs to be in an xml Node.** Here is sample of payload :

1
2
3
4
5
6
7
8
{
    "runtimes": {
        "nvidia": {
            "args": [],
            "path": "nvidia-container-runtime"
        }
    }
}

After Wrapping the json payload between xml token, our payload looks like this :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<json>
{
    "runtimes": {
        "nvidia": {
            "args": [],
            "path": "nvidia-container-runtime"
        }
    }
}
</json>

This is the xslt file used to translate JSON payload into XML.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ns0="myNamespace"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  expand-text="yes">

  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

  <xsl:mode on-no-match="shallow-copy"/>
	<xsl:template match="/json">
	  <xml xmlns:ns0="myNamespace">
	    <xsl:apply-templates select="json-to-xml(.)"/>
	  </xml>
	</xsl:template>

</xsl:stylesheet>

Here is the result of the script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<xml xmlns:ns0="myNamespace">
   <map xmlns="http://www.w3.org/2005/xpath-functions">
      <map key="runtimes">
         <map key="nvidia">
            <array key="args"/>
            <string key="path">nvidia-container-runtime</string>
         </map>
      </map>
   </map>
</xml>

Improved mapping

The result payload above is not really sexy. We have 2 options, either we add a complete new transformation or we had new templates in the current xslt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ns0="myNamespace"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  expand-text="yes">

  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

  <xsl:mode on-no-match="shallow-copy"/>
	<xsl:template match="/json">
	  <xml xmlns:ns0="myNamespace">
	    <xsl:apply-templates select="json-to-xml(.)"/>
	  </xml>
	</xsl:template>

	<!-- Template for "Runtimes" elements-->
	<xsl:template match="map" xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
		<Runtimes>
		<xsl:apply-templates select="//map[@key='nvidia']" />
		</Runtimes>
			<!-- select a sub-node structure  -->
	</xsl:template>

  <!-- Template for node Nvidia -->
  <xsl:template match="//map[@key='nvidia']" xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
    <Path><xsl:value-of select="string[@key='path']"/></Path>
    <Params>
      <xsl:for-each select="array[@key='args']/string">
        <Param><xsl:value-of select="."/></Param>
      </xsl:for-each>
    </Params>
  </xsl:template>

</xsl:stylesheet>

And now the output is more readable :

1
2
3
4
5
6
7
8
9
<xml xmlns:ns0="myNamespace">
   <Runtimes>
      <Path>nvidia-container-runtime</Path>
      <Params>
         <Param>dd</Param>
         <Param>aa</Param>
      </Params>
   </Runtimes>
</xml>