0

I'm trying to transform an xml input to a json output. My XSLT 1.0 is pretty proficient my XSLT 2.0/3.0 not so.

I thought I'd start with a hello world style template and build from there.

My belief is that you can simply create an output as map/array data structure and then some magic will map that into the desired output, so this is my first attempt (I've not defined an input, because any old xml will do in this example, it ignores it):

<?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"
    exclude-result-prefixes="xs"
    version="3.0">
    
    <xsl:output method="json" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/">
        <xsl:variable name="foo">
            <map xmlns="http://www.w3.org/2005/xpath-functions">
                <string key='desc'>Distances between several cities, in kilometers.</string>
                <string key='updated'>2014-02-04T18:50:45</string>
                <boolean key="uptodate">true</boolean>
                <null key="author"/>
                <map key='cities'>
                    <array key="Brussels">
                        <map>
                            <string key="to">London</string>
                            <number key="distance">322</number>
                        </map> 
                        <map>
                            <string key="to">Paris</string>
                            <number key="distance">265</number>
                        </map> 
                        <map>
                            <string key="to">Amsterdam</string>
                            <number key="distance">173</number>
                        </map> 
                    </array>
                </map>  
            </map>      
        </xsl:variable>
        <xsl:value-of select="xml-to-json($foo)"/>
    </xsl:template>
</xsl:stylesheet>

this almost works but I get a string output...(the '"' chars exist in the output file includeing all the escaping, so not a valid json output).

"{\"desc\":\"Distances between several cities, in kilometers.\",\"updated\":\"2014-02-04T18:50:45\",\"uptodate\":true,\"author\":null,\"cities\":{\"Brussels\":[{\"to\":\"London\",\"distance\":322},{\"to\":\"Paris\",\"distance\":265},{\"to\":\"Amsterdam\",\"distance\":173}]}}"

If there are any basic guides to do this, then please let me know, the web is awash with odd examples, out of date instruction based on XSLT 1.0/2.0 or hard to understand pdfs discussing more in depth scenarios.

MrD at KookerellaLtd
  • 2,412
  • 1
  • 15
  • 17

1 Answers1

0

The function you use already gives you a string with the JSON (see https://www.w3.org/TR/xpath-functions-31/#func-xml-to-json) so if you want to write that to a file just use <xsl:output method="text"/>.

The json output method mainly makes sense if you construct XDM/XPath 3.1 maps/arrays and want to serialize them as JSON.

For your sample I would also use <xsl:template name="xsl:initial-template"> instead of <xsl:template match="/">, then you don't need to provide any dummy input XML at all but can just start with that default named template using e.g. -it from the command line or callTemplate(null, ..) from the API.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • ah, is there any simple examples of this? (a nice XSLT 3.0 book wouldnt go amiss) – MrD at KookerellaLtd Oct 24 '22 at 10:57
  • @MrDatKookerellaLtd, your example is fine, you just need output method `text`, not `json`. I am currently not sure whether there is a good introductory text showing the need of `xsl:output method="text"` with `xml-to-json`, there are various articles around in the context of XPath 3.1 or XQuery 3.1 or XSLT 3.0 but I can't point to off the top of my head to one having the particular details. Chances are the XQuery for Humanists shows some use of `xml-to-json` with that output method, but of course with XQuery syntax. Most people have so far not managed to treat XSLT 3 in a book. – Martin Honnen Oct 24 '22 at 11:10
  • As for previous answers on StackOverflow, both https://stackoverflow.com/a/58105461/252228 and https://stackoverflow.com/a/58105051/252228 show the use of `xsl:output method="text"`. – Martin Honnen Oct 24 '22 at 11:14
  • https://stackoverflow.com/a/62571965/252228 shows both approaches. – Martin Honnen Oct 24 '22 at 11:16
  • https://www.saxonica.com/papers/xmlprague-2016mhk.pdf has at least one example using `xml-to-json` and `xsl:output method="text"`. – Martin Honnen Oct 24 '22 at 11:52
  • I think my confusions was that there are examples using method="text", but the method attribute supports "json" too, I'll mark the answer as an answer, though i think the answers in the comments are valuable to me. – MrD at KookerellaLtd Oct 24 '22 at 12:02