I have been checking related entries in SO and so far no luck, as my use case seems to have some commonalities but also differences with provided solutions (like: Converting json array to xml using XSLT or Convert JSON to XML using XSLT 3.0 functions).
so hopefully somebody can help me here please.
I call the transformation like this:
java -jar SaxonHE/saxon-he-11.4.jar -s:not_used.xml -xsl:rework_map.xsl -o:report-map.xml p1="list.json"
INPUT: list.json - file produced externally and not embedded in xml, containing array of entries, like:
[
{
"tc_id": "A_S_0001",
"file_name": "\\scripts\\A_S_0001.cs",
"version": "19",
"is_automated": true
},
{
"tc_id": "A_S_0002",
"file_name": "\\scripts\\A_S_0002.cs",
"version": "25",
"is_automated": false
}
]
EXPECTED OUTPUT: something like this:
<list>
<test_case>
<tc_id>A_S_0001</tc_id>
<file_name>\\scripts\\A_S_0001.cs</file_name>
<version>19</version>
<is_automated>true</is_automated>
</test_case>
<test_case>
<tc_id>A_S_0002</tc_id>
<file_name>\\scripts\\A_S_0002.cs</file_name>
<version>25</version>
<is_automated>false</is_automated>
</test_case>
</list>
my template rework_map.xsl (not working)
<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">
<!-- OUTPUT -->
<xsl:output method="xml" indent="yes"/>
<!-- PARAMETERS -->
<xsl:param name="p1"></xsl:param> <!-- list.json -->
<!-- VARIABLES -->
<xsl:variable name="json-array" select="json-doc($p1)"/>
<xsl:template match="/">
<!-- <xsl:call-template name="common.INFO"/> -->
<list>
<xsl:apply-templates select="$json-array/*"/>
</list>
</xsl:template>
<xsl:template match="fn:map">
<test_case>
<xsl:apply-templates/>
</test_case>
</xsl:template>
<xsl:template match="fn:map/fn:*">
<xsl:element name="{@key}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
One option with Saxon 11 is to feed the JSON files with the -json:list.json
option (don't use a -s
option) and write code along the lines of
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output indent="yes"/>
<xsl:template match=".[. instance of array(map(*))]" name="xsl:initial-template">
<list>
<xsl:apply-templates select="?*"/>
</list>
</xsl:template>
<xsl:template match=".[. instance of map(*)]">
<test_case>
<xsl:variable name="map" select="."/>
<xsl:iterate select="map:keys(.)">
<xsl:element name="{.}">{$map(.)}</xsl:element>
</xsl:iterate>
</test_case>
</xsl:template>
</xsl:stylesheet>
This directly processes the JSON as XPath 3.1 arrays/maps, the disadvantage is that XPath 3.1 maps have no order for the items in them so the result can be e.g.
<list>
<test_case>
<version>19</version>
<is_automated>true</is_automated>
<file_name>\scripts\A_S_0001.cs</file_name>
<tc_id>A_S_0001</tc_id>
</test_case>
<test_case>
<version>25</version>
<is_automated>false</is_automated>
<file_name>\scripts\A_S_0002.cs</file_name>
<tc_id>A_S_0002</tc_id>
</test_case>
</list>
The other option is to start with -it
for the initial-template
and use json-to-xml
and just write templates e.g.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output indent="yes"/>
<xsl:param name="json-string" as="xs:string" select="unparsed-text('list.json')"/>
<xsl:template name="xsl:initial-template">
<list>
<xsl:apply-templates select="json-to-xml($json-string)/*"/>
</list>
</xsl:template>
<xsl:template match="fn:map[not(@key)]">
<test_case>
<xsl:apply-templates/>
</test_case>
</xsl:template>
<xsl:template match="fn:*[@key and not(*)]">
<xsl:element name="{@key}">{.}</xsl:element>
</xsl:template>
</xsl:stylesheet>