Reputation: 23
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
Upvotes: 2
Views: 1581
Reputation: 167401
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.
Upvotes: 4
Reputation: 841
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>
</xsl:text>
<xsl:for-each select="root">
<xsl:text> </xsl:text><xsl:text>{</xsl:text>
<xsl:for-each select="header">
<xsl:text>
</xsl:text><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name()"/><xsl:text>"</xsl:text><xsl:text>:{
</xsl:text>
<xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(id)"/><xsl:text>":"</xsl:text><xsl:value-of select="id"/><xsl:text>"</xsl:text>
<xsl:text>
</xsl:text> <xsl:text> </xsl:text><xsl:text>},</xsl:text>
</xsl:for-each>
<xsl:for-each select="body">
<xsl:text>
</xsl:text><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name()"/><xsl:text>"</xsl:text><xsl:text>:{
</xsl:text>
<xsl:if test="user_name"><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(user_name)"/><xsl:text>":"</xsl:text><xsl:value-of select="user_name"/><xsl:text>",</xsl:text><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="code"><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(code)"/><xsl:text>":"</xsl:text><xsl:value-of select="code"/><xsl:text>",</xsl:text><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="date"><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(date)"/><xsl:text>":"</xsl:text><xsl:value-of select="date"/><xsl:text>",</xsl:text><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="time"><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(time)"/><xsl:text>":"</xsl:text><xsl:value-of select="time"/><xsl:text>",</xsl:text><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="timezone"><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(timezone)"/><xsl:text>":"</xsl:text><xsl:value-of select="timezone"/><xsl:text>",</xsl:text><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="mail"><xsl:text> </xsl:text><xsl:text>"</xsl:text><xsl:value-of select="local-name(mail)"/><xsl:text>":"</xsl:text><xsl:value-of select="mail"/><xsl:text>",</xsl:text><xsl:text>
</xsl:text></xsl:if>
<xsl:text> </xsl:text><xsl:text>}</xsl:text><xsl:text>
</xsl:text>
</xsl:for-each>
<xsl:text> }</xsl:text><xsl:if test="position()!=last()"><xsl:text>,</xsl:text></xsl:if><xsl:text>
</xsl:text>
</xsl:for-each>
<xsl:text>]</xsl:text>
</xsl:template>
</xsl:stylesheet>
DEMO https://xsltfiddle.liberty-development.net/ejivdHv
Upvotes: 1