简体   繁体   中英

convert XML to JSON via XSLT

Could you please provide XSLT code to convert from XML to JSON? I am SAP developer with zero
knowledge in XSLT. The XSLT must be able to convert the XML to JSON format as below.I need to convert an XML source to a specified JSON format. To do this i need to remove header nodes, retain the array body and encapsulate in [ ]. I have converted the body but i am having trouble removing the header nodes and inserting the encapsulating [ ]

This is the XML format I receive:

            <?xml version="1.0" encoding="utf-8"?>
            <n0:AA_JSON_Out xmlns:n0="http://PELASEHELP.com/PI/YYY"    "namespace
                  xmlns:prx="urn:sap.com:proxy:AAA:/1SAI/TAS3DF8912DDF823A9E7198:750">
                  <root>
                        <header>
                              <id>GGG-00009</id>
                        </header>
                        <body>
                              <user_name>RAMBO</user_name>
                              <code>BBB</code>
                              <date>20190405</date>
                              <time>015553</time>
                              <timezone>GMT</timezone>
                              <mail>52170302634</mail>
                        </body>
                  </root>
                  <root>
                        <header>
                              <id>GGG-00009</id>
                        </header>
                        <body>
                              <user_name>HULK</user_name>
                              <code>UUU</code>
                              <date>20190405</date>
                              <time>015553</time>
                              <timezone>GMT</timezone>
                        </body>
                  </root>
            </n0:AA_JSON_Out>


This is what need to produce:
            [{"header":{},"body":{}},{"header":{},"body":{}}]

        Below is the output code `enter code here`result.
            [ 
               { 
                  "header":{ 
                     "id":"GGG-00009"
                  },
                  "body":{ 
                     "user_name":"RAMBO",
                     "code":"BBB",
                     "date":"20190405",
                     "time":"015553",
                     "timezone":"GMT",
                     "identfier":"52170302317"
                  }
               },
               { 
                  "header":{ 
                     "id":"GGG-00009"
                  },
                  "body":{ 
                     "user_name":"HULK",
                     "code":"UUU",
                     "date":"20190405",
                     "time":"015553",
                     "timezone":"GMT"
                  }
               }
                 ]

XSLT Code:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">[<xsl:apply-templates select="@* | node()"/>]</xsl:template>

    <!-- Object or Element Property-->
    <xsl:template match="*">
            <xsl:variable name="childName" select="name()" /><xsl:if test="not(contains($childName, 'root')) and not(contains($childName, 'n0'))">"<xsl:value-of select="normalize-space(name())"/>":</xsl:if><xsl:call-template name="Properties"/>
    </xsl:template>

    <!-- Array Element -->
    <xsl:template match="*" mode="ArrayElement">
        <xsl:call-template name="Properties"/>
    </xsl:template>


    <!-- Object Properties -->
    <xsl:template name="Properties">
        <xsl:variable name="childName" select="name()"/>
        <xsl:choose><xsl:when test="not(*|@*)">"<xsl:value-of select="."/>"</xsl:when><xsl:when test="count(*[name()=$childName]) > 1"> 

        "<xsl:value-of select="$childName"/>" :[<xsl:apply-templates select="*" mode="ArrayElement"/>] </xsl:when>
            <xsl:otherwise><xsl:if test="not(contains($childName, 'root'))">{</xsl:if>
            <xsl:apply-templates select="@*"/><xsl:apply-templates select="*"/><xsl:if test="not(contains($childName, 'root'))">}</xsl:if></xsl:otherwise>


        </xsl:choose>

        <xsl:if test="(contains($childName, 'body'))">}</xsl:if> 
        <xsl:if test="following-sibling::*">,</xsl:if>


    </xsl:template>

    <!-- Attribute Property -->
    <xsl:template match="@*">"<xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>",
    </xsl:template>
</xsl:stylesheet>

    Please help me to provide XSLT code.
            Thank you,
            S,Saravannan

If you can move to XSLT 3 then you can map XML to XPath 3.1 arrays and maps that can be directly serialized as JSON:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="json" indent="yes" />

  <xsl:template match="/*">
    <xsl:sequence
      select="array { 
                       root ! 
                       map:merge(
                          * ! map { local-name() : map:merge(* ! map:entry(local-name(), string())) }
                       )
                     }"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/94AbWBr

XSLT 3 is implemented for Java , .NET and C/C++/Python/PHP by Saxon 9 as well as by Altova XMLSpy and Raptor.

For instance, with the new Python API in Saxon-C 1.2.1 you can use

import saxonc
import os

with saxonc.PySaxonProcessor() as proc:
    print(proc.version)

    xslt30_processor = proc.new_xslt30_processor()

    xslt30_processor.set_cwd(os.getcwd())

    xslt30_processor.apply_templates_returning_file(source_file = 'input-sample-to-transform-to-json1.xml', stylesheet_file = 'xml-to-xpath-31-array-and-maps-serialized-as-json1.xsl', output_file = 'example-json-output1.json')

to run the given stylesheet against an input sample and create a JSON result file.

XSLT 1.0 you can try this:

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:n0="http://PELASEHELP.com/PI/YYY"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="1.0">
    <xsl:output method="text" omit-xml-declaration="yes"/>

    <xsl:template match="n0:AA_JSON_Out">
        <xsl:text>[</xsl:text><xsl:text>&#x0A;</xsl:text>
        <xsl:for-each select="root">
            <xsl:text>   </xsl:text><xsl:text>{</xsl:text>
            <xsl:for-each select="header">
                <xsl:text>&#x0A;</xsl:text><xsl:text>  </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name()"/><xsl:text>&quot;</xsl:text><xsl:text>:{&#x0A;</xsl:text>
                <xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(id)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="id"/><xsl:text>&quot;</xsl:text>
                <xsl:text>&#x0A;</xsl:text> <xsl:text>  </xsl:text><xsl:text>},</xsl:text>
            </xsl:for-each>
            <xsl:for-each select="body">
                <xsl:text>&#x0A;</xsl:text><xsl:text>  </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name()"/><xsl:text>&quot;</xsl:text><xsl:text>:{&#x0A;</xsl:text>
                <xsl:if test="user_name"><xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(user_name)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="user_name"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if>
                <xsl:if test="code"><xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(code)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="code"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if>
                <xsl:if test="date"><xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(date)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="date"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if>
                <xsl:if test="time"><xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(time)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="time"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if>
                <xsl:if test="timezone"><xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(timezone)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="timezone"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if>
                <xsl:if test="mail"><xsl:text>   </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(mail)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="mail"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if>
                <xsl:text>   </xsl:text><xsl:text>}</xsl:text><xsl:text>&#x0A;</xsl:text>
            </xsl:for-each>
            <xsl:text>    }</xsl:text><xsl:if test="position()!=last()"><xsl:text>,</xsl:text></xsl:if><xsl:text>&#x0A;</xsl:text>
        </xsl:for-each>
        <xsl:text>]</xsl:text>
    </xsl:template>
</xsl:stylesheet>

DEMO https://xsltfiddle.liberty-development.net/ejivdHv

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM