XSLT3.0 | JSON-XML Conversion

Viewed 42

I'm trying to convert json to xml using xslt 3.0 (Saxon-HE v11.4 library) in Java.

While i'm able to convert the complete json to xml, i need guidance in writing a custom logic to pick and choose keys that needs to be in final xml.

XSLT being used currently -

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*" />
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:param name="inputJson" />

    <xsl:template name="init">
        <xsl:apply-templates
            select="json-to-xml($inputJson)" />
    </xsl:template>

    <!-- template to keep json keys as xml keys -->
    <xsl:template match="*[@key]">
        <xsl:element name="{@key}">
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <!-- template to remove namespace -->
    <xsl:template match="data">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()" />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Sample json -

{
    "name": "user",
    "age": 20,
    "designation": "engineer",
    "addresses": [
        {
            "type": "home",
            "address": "sample address 1"
        },
        {
            "type": "work",
            "address": "sample address 2"
        }
    ]
}

Current XML Output (which needs fix, as individual type/address element is not surrounded by addresses tag) -

<name>user</name>
<age>20</age>
<designation>engineer</designation>
<addresses>
   <type>home</type>
   <address>sample address 1</address>
   <type>work</type>
   <address>sample address 2</address>
</addresses>

I would need the final XML to have name , age and home address. Sample expected XML -

<name>user</name>
<age>20</age>
<home-address>
    <addressLine>sample address 1</addressLine>
</home-address>

Any help would be much appreciated.

1 Answers

Either use various transformation steps with e.g. different modes or write conditions in your match patterns like e.g.

<xsl:template match="fn:array[@key = 'addresses']">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="fn:map[fn:string[@key = 'address'] and fn:string[@key = 'type']]">
  <xsl:element name="{fn:string[@key = 'type']}-address">
    <addressLine>{fn:string[@key = 'address']}</addressLine>
  </xsl:element>
</xsl:template>

That needs xmlns:fn="http://www.w3.org/2005/xpath-functions" and expand-text="yes" on e.g. the xsl:stylesheet root element.

Fiddle example.

Related