Other articles on this site have described the JSON support we have added to our XSLT 2.0 and XPath 2.0 products (see A SAX-like Parser for JSON, XSLT and XPath for JSON, and our XJR SDK.). In this article, we describe two additional extensions to our XSLT 2.0 and DOM parser products to support the output of JSON documents. The following XSLT example is currently running in our unit tests. We have kept it simple so it would fit here and yet convey the power of our tools.
First, here is the XSLT template that generates JSON:
<?xml version='1.0' encoding='UTF-8'?> <xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <xsl:output method='json'/> <xsl:variable name='gtlist' select='/staff/employee/name'/> <xsl:template match='/'> {{ "employee": <xsl:text> [</xsl:text> <xsl:for-each select='$gtlist'> <xsl:sort select='.' /> "<xsl:value-of select='.' />" <xsl:if test='position() != last()'>,\n </xsl:if> </xsl:for-each> <xsl:text>]\n}}</xsl:text> </xsl:template> </xsl:stylesheet>
The following also works to select JSON as the output method (i.e., it uses a proper QName for the method value):
<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:jn='http://www.json.org' <xsl:output method='jn:json'/> * * * * *
Or we can generate JsonML by the following modification to the top of the above template:
<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:jm='http://www.jsonml.org'> <xsl:output method='jm:jsonml'/> * * * * *
Notice the necessity of using the double “{{” and “}}” characters because curly brakets are meaningful in XSLT (e.g., attribute value templates). The “{{” produces a single “{” in the output, and the “}}” character sequence produces a single “}” in the output. Also of interest is that our style sheet is using XSLT sorting.
Second, we have two forms of the ‘source’ document that we apply to the template above to produce a JSON output document. We have encoded the same information in XML and JSON. Here is the XML form of the source document:
<?xml version='1.0' encoding='UTF-8' ?> <staff> <employee> <name>Henry Joseph</name> <hiredate>2007-01-09</hiredate> </employee> <employee> <name>Irvin Joseph</name> <hiredate>2003-06-12-03:05</hiredate> </employee> <employee> <name>Izzy Joseph</name> <hiredate>1998-11-03</hiredate> </employee> <employee> <name>Basil Joseph</name> <hiredate>1998-11-03</hiredate> </employee> <employee> <name>Mark Joseph</name> <hiredate>2004-07-12-08:00</hiredate> </employee> <employee> <name>Jim Susoy</name> <hiredate>2004-07-12-08:00</hiredate> </employee> </staff>
And here is the JSON form of the source document:
{ "staff": { "employee": [ {"name":"Henry Joseph", "hiredate":"2007-01-09"}, {"name":"Irvin Joseph", "hiredate":"2003-06-12-03:00"}, {"name":"Izzy Joseph", "hiredate":"1998-11-03:00"}, {"name":"Basil Joseph", "hiredate":"1998-11-03"}, {"name":"Mark Joseph", "hiredate":"2004-07-12-08:00"}, {"name":"Jim Susoy", "hiredate":"2004-07-12-08:00"} ] } }
The result document when running the XSLT template against either of the source documents above is the same sorted list:
{"employee": ["Basil Joseph", "Henry Joseph", "Irvin Joseph", "Izzy Joseph", "Jim Susoy", "Mark Joseph"] }
(However, as defined in our XSLT and XPath for JSON article when the source document is in JSON the XPath path expressions have to be changed slightly. So in the XSLT template above the XPath path expression ” select=’/staff/employee/name’ ” is changed to ” select=’/JSON-document/staff/employee/name’ “. See the above mentioned article for an explanation.)
Now the cool thing to notice with our JSON-enabled XSLT processor is that the following transformations are possible: JSON to any of the forms { JSON, XML, Text, HTML, XHTML }, and XML to any of the forms { JSON, XML, Text, HTML, XHTML }. (A JSON to JSON transformation refers to taking one JSON document and re-arranging / adding / removing elements to form a new JSON document.)
DOM Object Support
Once a source document (either in XML or JSON) is parsed into one of our DOM objects, the developer has the option of three DOM API functions that support document output.
First, the developer can select to output the entire DOM tree via the function:
p6IDOMXML::output( p6IDataStream* pStream, P6DOMOUTPUT flags, ... );
Where ‘P6DOMOUTPUT’ can be one of the following: { P6DOMOUTPUT_XML, P6DOMOUTPUT_JSON } and the default character set is UTF-8.
Or the developer can output any sub tree rooted from a node object that is currently selected, via the methods:
// For XML output p6IXMLNode::outputSubTree( p6IDataStream* pOutput, P6DOMCHARSET charSet ); // Or for JSON output p6IXMLNode::outputSubTreeInJSON( p6IDataStream* pOutput, P6DOMCHARSET charSet );
(Note, a p6IDataStream pointer can be to a file, a network socket, etc.) Here a node in the DOM tree is selected either from evaluating an XPath expression or via walking the tree via the native DOM API.
Our DOM API allows the same DOM tree to be output in either XML or JSON format no matter what its original form was. Of course, since JSON does not have ‘element’ attributes any attributes from an XML source will not appear in a JSON output document.