2

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
3
  • Can you show us your XSLT-Code for the body, so we can see what you already have tried. Commented Dec 16, 2019 at 8:15
  • 1
    StackOverflow is for helping with specific programming problems you encounter while programming yourself. It sadly is not for providing desired solutions. Commented Dec 16, 2019 at 8:24
  • 1
    Hi All, I have added the XSLT code. Commented Dec 16, 2019 at 8:37

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

7 Comments

Hi Sandy. I have tried and below is the output, SAP-00009 SARAVNN 617 SAP-00010 SARAVNN 617. All the ",{} is missing.
Hi Saravannan, You can check result.
Hello Sandy, Yes it seems it is working now and I will try the full cycle process....Really appreciate your help and others help. Is there any way i should reward you..
@SaravannanSithambaram Please read the help page to inform yourself about how to properly use StackOverflow: stackoverflow.com/help
Hello Sandy, One question. How do I add condition in this statement: ! <xsl:if test="mail_identfier"><xsl:text> </xsl:text><xsl:text>&quot;</xsl:text><xsl:value-of select="local-name(mail_identfier)"/><xsl:text>&quot;:&quot;</xsl:text><xsl:value-of select="mail_identfier"/><xsl:text>&quot;,</xsl:text><xsl:text>&#x0A;</xsl:text></xsl:if> ! Example: if the value is 1 than local name 'XX' and if the value is 2 local name 'YY.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.