How to Convert JSON to XML with XSLT 3.0

Working in a microservice architecture often includes service requests that return a JSON data structure instead of XML. I am personally not a friend of JSON because I think XML is more accurate than JSON when dealing with complex data structures. And with XSL there is also a mature and powerful template technique to adapt XML data structures to your own needs. But any way, we have to take what we have.

JSON and XSLT 3.0

The good news first: XSLT 3.0 can deal with JSON. So we can use the XSL template technique to transform JSON either into XML or a new format which fits best your application data structures. Let’s assume the following XML data containing a JSON structure:

<data>{
	"content": [
	  {
	    "id": 70805774,
	    "value": "1001",
	    "position": [1004.0,288.0,1050.0,324.0]
	  }
	]
}</data>

Working with XSLT, the JSON structure must be packed into a XML tag. In my case this the <data> tag

Now you can use the XSL function json-to-xml to convert the JSON into a XML structure. With the following template you will see how XSL 3.0 deals with JSON:

<?xml version="1.0"?>
<xsl:stylesheet
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:math="http://www.w3.org/2005/xpath-functions/math"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	exclude-result-prefixes="xs math" version="3.0">
	<xsl:output indent="yes" omit-xml-declaration="yes" />

	<xsl:template match="data">
	    <xsl:copy-of select="json-to-xml(.)"/>
	</xsl:template>
</xsl:stylesheet>

Based on the JSON example above this will result in the following output:

<map xmlns="http://www.w3.org/2005/xpath-functions">
   <array key="content">
      <map>
         <number key="id">70805774</number>
         <string key="value">1001</string>
         <array key="position">
            <number>1004.0</number>
            <number>288.0</number>
            <number>1050.0</number>
            <number>324.0</number>
         </array>
      </map>
   </array>
</map>

As you can see, the XSLT processor creates ‘map’ and ‘array’ tags to structure the data in a XML schema. It also converts numbers, strings and booleans into a corresponding XML tag. After you have transformed a JSON data structure with the function json-to-xml you can next transform this data using the template technique.

Take a look at the following example:

<?xml version="1.0"?>
<xsl:stylesheet
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:math="http://www.w3.org/2005/xpath-functions/math"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	exclude-result-prefixes="xs math" version="3.0">
	<xsl:output indent="yes" omit-xml-declaration="yes" />
	
	<xsl:template match="data">
		<!-- create a new root tag -->
		<my-document>
			<!-- apply the xml structure generated from JSON -->
			<xsl:apply-templates select="json-to-xml(.)" />
		</my-document>
	</xsl:template>

	<!-- template for the first tag -->
	<xsl:template match="map"
		xpath-default-namespace="http://www.w3.org/2005/xpath-functions">

		<position>
			<!-- select a sub-node structure  -->
			<xsl:apply-templates select="array[@key='content']/map/array[@key='position']/number" />
		</position>
		
	</xsl:template>
		
	<!-- template to output a number value -->
	<xsl:template match="number"
		xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
		<num>
			<xsl:value-of select="." />
		</num>
	</xsl:template>

</xsl:stylesheet>

In this template example I create first a new xml-root tag ‘my-document’. Next – and this is important – I apply a template on the new JSON-to-XML structure. And so I can create some matching templates to select and transform different parts of the XML. The first matching template in my example selects the data of the ‘position’ array which is a sub node of the ‘content’ array. This is a general XSLT/XPath technique and you can apply any kind of template here. It should only demonstrate the power of XSLT.

The outcome of this example will look like this:

<my-document>
   <position>
      <num>1004.0</num>
      <num>288.0</num>
      <num>1050.0</num>
      <num>324.0</num>
   </position>
</my-document>

I hope this helps you to get started with converting your own JSON results.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.