Mercurial > pub > ModelGenerator
diff xslt/json.xsl @ 12:191b81b2052b
first version of the xslt transform from xml to json
author | cin |
---|---|
date | Mon, 09 Apr 2018 06:43:46 +0300 |
parents | 14162f9133a1 |
children | 197a850b1f6f |
line wrap: on
line diff
--- a/xslt/json.xsl Sun Apr 08 23:30:11 2018 +0300 +++ b/xslt/json.xsl Mon Apr 09 06:43:46 2018 +0300 @@ -1,33 +1,70 @@ <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:exsl="http://exslt.org/common"> <xsl:output method="text" /> + + <xsl:key name="members" match="*" use="concat(generate-id(..),local-name(.))"/> - <xsl:template match="*[count(*) = 0]"> - <xsl:apply-templates mode="json-value" /> - </xsl:template> - - <xsl:template match="*[count(*) > 0]"> - <xsl:text>{ </xsl:text> - <xsl:apply-templates mode="json-object-member"/> - <xsl:text> }</xsl:text> + <xsl:template match="/"> + <xsl:variable name="doc"> + <xsl:apply-templates/> + </xsl:variable> + <xsl:apply-templates select="exsl:node-set($doc)" mode="json-value" /> </xsl:template> - <xsl:template match="text()"/> - + <xsl:template match="*"> + <xsl:copy> + <xsl:apply-templates select="@*"/> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <xsl:template match="@*"> + <xsl:copy/> + </xsl:template> + <!-- handle json-object --> - <xsl:template name="write-object"> - + <xsl:template match="*" mode="json-object-members"> + <xsl:apply-templates select="." mode="json-object-members-internal"/> </xsl:template> - + + <xsl:template match="*" mode="json-object-members-internal"> + <xsl:variable name="oid" select="generate-id(.)"/> + <xsl:variable name="grouped" select="*[generate-id(.) = generate-id(key('members',concat($oid,local-name(.))))]"/> + <xsl:apply-templates select="$grouped" mode="json-object-member"/> + </xsl:template> + <xsl:template match="*" mode="json-object-member"> - <xsl:call-template name="write-json-string"> + <xsl:call-template name="write-string"> <xsl:with-param name="text" select="local-name(.)"/> </xsl:call-template> <xsl:text> : </xsl:text> - <xsl:apply-templates mode="json-value"/> + <xsl:apply-templates select="." mode="json-member-value"/> + <xsl:if test="position() != last()"> + <xsl:text>, </xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="*" mode="json-member-value"> + <xsl:variable name="oid" select="generate-id(..)"/> + <xsl:variable name="values" select="key('members',concat($oid,local-name(.)))"/> + <xsl:choose> + <xsl:when test="count($values) > 1"> + <xsl:call-template name="write-array"> + <xsl:with-param name="values" select="$values"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="$values" mode="json-value"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="*" mode="json-array-item"> + <xsl:apply-templates select="." mode="json-value"/> <xsl:if test="position() != last()"> <xsl:text>, </xsl:text> </xsl:if> @@ -35,10 +72,6 @@ <!-- handle json-value --> - <xsl:template match="*[@xsi:nil = 'true']"> - <xsl:text>null</xsl:text> - </xsl:template> - <xsl:template match="text()[. = 'true']" mode="json-value"> <xsl:text>true</xsl:text> </xsl:template> @@ -54,19 +87,64 @@ </xsl:template> <xsl:template match="text()" mode="json-value"> - <xsl:call-template name="write-json-string"> + <xsl:call-template name="write-string"> <xsl:with-param name="text" select="."/> </xsl:call-template> </xsl:template> - <xsl:template match="*" mode="json-value"> - <xsl:apply-templates select="."/> + <xsl:template match="*[boolean(* | @*) or not(text())]" mode="json-value"> + <xsl:call-template name="write-object"/> + </xsl:template> + + <xsl:template match="*[@xsi:nil = 'true']" mode="json-value"> + <xsl:text>null</xsl:text> </xsl:template> <!-- template traits --> - <xsl:template name="write-json-string"> + + <xsl:template name="write-value"> + <xsl:param name="value" select="."/> + <xsl:apply-templates select="exsl:node-set($value)" mode="json-value"/> + </xsl:template> + + <xsl:template name="write-named-value"> + <xsl:param name="name"/> + <xsl:param name="value"/> + <xsl:call-template name="write-string"> + <xsl:with-param name="text" select="$name"/> + </xsl:call-template> + <xsl:text> : </xsl:text> + <xsl:apply-templates select="exsl:node-set($value)"/> + </xsl:template> + + <!-- specialized template traits --> + + <xsl:template name="write-string"> <xsl:param name="text"/> <xsl:value-of select="concat('"', $text,'"')" /> </xsl:template> + + <xsl:template name="write-object"> + <xsl:param name="value" select="."/> + <xsl:text>{ </xsl:text> + <xsl:apply-templates select="$value" mode="json-object-members"/> + <xsl:text> }</xsl:text> + </xsl:template> + + <xsl:template name="write-array"> + <xsl:param name="oid" select="generate-id(..)"/> + <xsl:param name="values" select="key('members',concat($oid,local-name(.)))"/> + + <xsl:text>[ </xsl:text> + <xsl:apply-templates select="$values" mode="json-array-item"/> + <xsl:text> ]</xsl:text> + </xsl:template> + + <xsl:template name="write-object-members"> + <xsl:param name="object" select="."/> + <xsl:for-each select="exsl:node-set($object)"> + <xsl:apply-templates select="." mode="json-object-members-internal"/> + </xsl:for-each> + </xsl:template> </xsl:stylesheet> \ No newline at end of file