Reputation: 53
i have a front end page that send a request to an data service deployed to wso2 console for doing an update in a table. The problem is that i need to convert the json array from the front end to an xml format for build the payload factory for the request. The json is :
{"cdcList":
["UpdateCdc":
{
"idCdc":1,
"order":1,
"cdcName":"test 1",
},
"UpdateCdc":
{
"idCdc":2,
"order":2,
"cdcName":"test 2",
"idParent":1
},
"UpdateCdc":
{
"idCdc":3,
"order":1,
"cdcName":"test 3",
"idParent":1
}
]
}
and the desired result in xml that i would like that it will be is :
<cdcList>
<UpdateCdc>
<idCdc>1</idCdc>
<order>1</order>
<cdcName>test 1</cdcName>
</UpdateCdc>
<UpdateCdc>
<idCdc>2</idCdc>
<order>2</order>
<cdcName>test 2</cdcName>
<idParent>1</idParent>
</UpdateCdc>
<UpdateCdc>
<idCdc>3</idCdc>
<order>3</order>
<cdcName>test 3</cdcName>
<idParent>1</idParent>
</UpdateCdc>
</cdcList>
Thank you.
Upvotes: 1
Views: 3467
Reputation: 167401
While Michael Kay's answer gives you XML (see it online at https://xsltfiddle.liberty-development.net/bFDb2Cf/) I think it has one shortcoming, the order of the keys of an XPath 3.1 map is not defined so with map:keys
you might get any order for the child elements (e.g. in the linked example it is idParent
, idCdc
, cdcName
, order
) while you probably want to define the order for the child elements based on the order in the JSON. That can be achieved using the json-to-xml
function already mentioned by Tim in a comment:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array fn"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="json-input" as="xs:string">[
{
"idCdc": 1,
"order": 1,
"cdcName": "test 1"
},
{
"idCdc": 2,
"order": 2,
"cdcName": "test 2",
"idParent": 1
},
{
"idCdc": 3,
"order": 1,
"cdcName": "test 3",
"idParent": 1
}
]</xsl:param>
<xsl:variable name="json-array" select="parse-json($json-input)"/>
<xsl:variable name="json-xml" select="json-to-xml($json-input)"/>
<xsl:template match="/">
<cdcList>
<xsl:apply-templates select="$json-xml/*"/>
</cdcList>
</xsl:template>
<xsl:template match="fn:map">
<updateCdc>
<xsl:apply-templates/>
</updateCdc>
</xsl:template>
<xsl:template match="fn:map/fn:*">
<xsl:element name="{@key}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bFDb2Cf/2 has that example, in https://xsltfiddle.liberty-development.net/bFDb2Cf/1 I also output the result of the json-to-xml
call so that you can see how the JSON input is mapped to XML:
<array xmlns="http://www.w3.org/2005/xpath-functions">
<map>
<number key="idCdc">1</number>
<number key="order">1</number>
<string key="cdcName">test 1</string>
</map>
<map>
<number key="idCdc">2</number>
<number key="order">2</number>
<string key="cdcName">test 2</string>
<number key="idParent">1</number>
</map>
<map>
<number key="idCdc">3</number>
<number key="order">1</number>
<string key="cdcName">test 3</string>
<number key="idParent">1</number>
</map>
</array>
Upvotes: 2
Reputation: 163262
To do client-side processing in XSLT with support for JSON parsing you will need an XSLT 3.0 processor, which in practice means Saxon-JS. (Disclaimer: that's my company's product.)
Unfortunately the input you supplied isn't valid JSON, but let's assume it is actually like this:
[
{
"idCdc": 1,
"order": 1,
"cdcName": "test 1"
},
{
"idCdc": 2,
"order": 2,
"cdcName": "test 2",
"idParent": 1
},
{
"idCdc": 3,
"order": 1,
"cdcName": "test 3",
"idParent": 1
}
]
Then you can convert it to your desired XML format using the following XSLT 3.0 code:
<xsl:variable name="json-array" select="json-doc('input.json')"/>
<cdcList>
<xsl:for-each select="$json-array?*">
<updateCdc>
<xsl:for-each select="map:keys(.)">
<xsl:element name="{.}">
<xsl:value-of select="map:get(.)"/>
</xsl:element>
</xsl:for-each>
</updateCdc>
</xsl:for-each>
</cdcList>
Upvotes: 2