Reputation: 400
Recent Saxon releases contain a command line argument "-json:myfile.json" to input a JSON file.
But how do I implement the XSLT to parse this JSON? I did not find any doc which handles this directly (without making use of "json-to-xml" or similar).
I only found this: how to convert json to xml with saxonjs?
But this does not help me, because my json starts with an array:
[
{
"eid": "2122.5",
"ecat": "show",
"day": "1629410400",
"spcat": "Bühne",
"time": "19:30",
"text": "Welle",
"remarks": "",
"location": ""
},
{
"eid": "2122.6",
"ecat": "show",
"day": "1629496800",
"spcat": "Bühne",
"time": "19:30",
"text": "Welle",
"remarks": "",
"location": ""
}
]
By writing an intermediate XSLT using the function "json-to-xml", I can convert this JSON to xml that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<array xmlns="http://www.w3.org/2005/xpath-functions">
<map>
<string key="eid">2122.5</string>
<string key="ecat">show</string>
<string key="day">1629410400</string>
<string key="spcat">Bühne</string>
<string key="time">19:30</string>
<string key="text">Welle</string>
<string key="remarks"/>
<string key="location"/>
</map>
<map>
<string key="eid">2122.6</string>
<string key="ecat">show</string>
<string key="day">1629496800</string>
<string key="spcat">Bühne</string>
<string key="time">19:30</string>
<string key="text">Welle</string>
<string key="remarks"/>
<string key="location"/>
</map>
</array>
How can I create a template that matches the root item, and how can I call "apply-templates" to trigger another template that handles the items?
Upvotes: 0
Views: 940
Reputation: 167706
The JSON you have shown is an array so it will be mapped to the XPath/XSLT XDM type array(*)
, or, in your case, array(map(xs:string, xs:string))
. To match on that use e.g. <xsl:template match=".[. instance of array(*)]">..</xsl:template>
or e.g. <xsl:template match=".[. instance of array(map(xs:string, xs:string))]">..</xsl:template>
.
More complete example would be online at the fiddle, doing:
<?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 method="xml" indent="yes"/>
<xsl:template match=".[. instance of array(map(xs:string, xs:string))]">
<items>
<xsl:apply-templates select="?*"/>
</items>
</xsl:template>
<xsl:template match=".[. instance of map(xs:string, xs:string)]">
<xsl:variable name="map" select="."/>
<item>
<xsl:iterate select="map:keys(.)">
<value key="{.}">{$map(.)}</value>
</xsl:iterate>
</item>
</xsl:template>
</xsl:stylesheet>
As for grouping:
<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 method="xml" indent="yes"/>
<xsl:template match=".[. instance of array(map(xs:string, xs:string))]">
<items>
<xsl:for-each-group select="?*" group-by="?text">
<group name="{current-grouping-key()}">
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:for-each-group>
</items>
</xsl:template>
<xsl:template match=".[. instance of map(xs:string, xs:string)]">
<xsl:variable name="map" select="."/>
<item>
<xsl:iterate select="map:keys(.)[not(. = current-grouping-key())]">
<value key="{.}">{$map(.)}</value>
</xsl:iterate>
</item>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1