Search code examples
xmlxpathxslt

Using XSLT to parse non-wrapped json


In all the xslt examples I've seen for converting json to xml, the json is always wrapped in xml tags before processing using the json-to-xml() function. I'm curious if it's possible to do the conversion without wrapping the json. I've been playing with this xslt fiddle to no avail, but if I wrap it in <data></data> and then change the input type to xml it works. Does anyone have any guidance on how to get the xslt in the fiddle to work with bare json?

<?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"
  exclude-result-prefixes="#all">
  
  <xsl:template match="/">
      <xsl:copy-of select="json-to-xml(.)"/>
  </xsl:template>
  
</xsl:stylesheet>

Solution

  • I don't know exactly how the Fiddle invokes Saxon, but I suspect that when you select the input type as JSON, it actually parses the JSON and supplies the resulting structure of maps and arrays as the initial context item. Unfortunately the json-to-xml() function expects unparsed lexical JSON as input, so the only way I can make this work is to re-serialize the JSON, like this:

    <xsl:template match=".">
          <xsl:copy-of select="serialize(., 
             map{'method':'json'}) => json-to-xml()"/>
    </xsl:template>
    

    Note the match="." rather than match="/", because "/" will only match the root of an XML document, whereas "." will match anything.

    If you weren't constrained by the way the Fiddle is implemented, you could supply the JSON content to the stylesheet as a string, or as the URI of a file, which you could read using unparsed-text().