Search code examples
javaxmlsaxonxslt-3.0

JSON to XML Transformation using XSLT 3.0


I am using Java 1.8, Saxon-HE version 9.9.1-4 version and xslt3.0 to tranform the JSON to XML.

Input JSON

{
    "analystId": "Test",
    "jobId": "",
    "profileData": {
        "allAuthorCoverage": false,
        "assetClasses": [
            {
                "code": "Test1"
            }
        ]
        
    }   
}

XSLT3.0

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" /> 
  <xsl:strip-space elements="*"/>
  <xsl:param name="jsonText"/>

  <xsl:template match="@*|node()"> 
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template> 

  <xsl:template name="init">
    <xsl:apply-templates select="json-to-xml($jsonText)"/> 
  </xsl:template>
  
 <xsl:template match="*[@key]" >
  <xsl:element name="{@key}">
    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

Output XML Generated

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
   <analystId xmlns="">Test</analystId>
   <jobId xmlns=""/>
   <profileData xmlns="">
      <allAuthorCoverage>false</allAuthorCoverage>
      <assetClasses>
         <map xmlns="http://www.w3.org/2005/xpath-functions">
            <code xmlns="">Test1</code>
         </map>
      </assetClasses>
   </profileData>
</map>

Output XML Expected

<?xml version="1.0" encoding="UTF-8"?>
<analystId>Test</analystId>
<jobId />
<profileData>
    <allAuthorCoverage>false</allAuthorCoverage>
    <assetClasses>
        <code>Test1</code>
    </assetClasses>
</profileData>

We can still see <map> element and xmlns attribute in the generated output and my requirement is to remove the same.

How can I remove the Map element from the generated output and xmlns attribute as well?

Also in case I expand my JSON structure with new attributes these map element and xmlns attribute should not be added back again.


Solution

  • If you don't use the identity template you have used and instead omit it only your template to transform elements with a key attribute into elements of the name of the key value and any text nodes will create output:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="#all">
    
        <xsl:param name="jsonText" as="xs:string"><![CDATA[{
        "analystId": "Test",
        "jobId": "",
        "profileData": {
            "allAuthorCoverage": false,
            "assetClasses": [
                {
                    "code": "Test1"
                }
            ]
    
        }   
    }]]></xsl:param>
    
        <xsl:output indent="yes" /> 
        <xsl:strip-space elements="*"/>
    
        <xsl:template name="xsl:initial-template">
            <xsl:apply-templates select="json-to-xml($jsonText)"/> 
        </xsl:template>
    
        <xsl:template match="*[@key]" >
            <xsl:element name="{@key}">
                <xsl:apply-templates/>
            </xsl:element>
        </xsl:template>
    
    </xsl:stylesheet>