Mercurial > pub > ImplabNet
view Implab/Xml/json.xsl @ 281:e0916ddc9950 v3 tip
code cleanup and refactoring
author | cin |
---|---|
date | Fri, 01 Jun 2018 21:35:24 +0300 |
parents | 3a6e18c432be |
children |
line wrap: on
line source
<?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:exsl="http://exslt.org/common"> <xsl:output method="text" /> <xsl:template match="/"> <xsl:apply-templates mode="json-value" /> </xsl:template> <!-- handle json-object --> <xsl:template match="*" mode="json-object"> <xsl:call-template name="write-members"/> </xsl:template> <xsl:template match="*|@*" mode="json-member"> <xsl:param name="values" select="."/> <xsl:call-template name="write-string"> <xsl:with-param name="text"><xsl:apply-templates select="." mode="json-member-name"/></xsl:with-param> </xsl:call-template> <xsl:text> : </xsl:text> <xsl:apply-templates select="." mode="json-member-value"> <xsl:with-param name="values" select="$values"/> </xsl:apply-templates> </xsl:template> <xsl:template match="*" mode="json-member-name"> <xsl:value-of select="local-name(.)"/> </xsl:template> <xsl:template match="@*" mode="json-member-name"> <xsl:value-of select="concat('_',local-name(.))"/> </xsl:template> <xsl:template match="*|@*" mode="json-member-value"> <xsl:param name="values" select="."/> <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> </xsl:template> <!-- handle json-value --> <xsl:template match="text()[. = 'true'] | @*[. = 'true']" mode="json-value"> <xsl:text>true</xsl:text> </xsl:template> <xsl:template match="text()[. = 'false'] | @*[. = 'false']" mode="json-value"> <xsl:text>false</xsl:text> </xsl:template> <xsl:template match="text()[string(number(.)) != 'NaN'] | @*[string(number(.)) != 'NaN']" mode="json-value"> <xsl:value-of select="number(.)" /> </xsl:template> <xsl:template match="text()|@*" mode="json-value"> <xsl:call-template name="write-string"> <xsl:with-param name="text" select="."/> </xsl:call-template> </xsl:template> <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-value"> <xsl:param name="value" select="."/> <xsl:apply-templates select="$value" mode="json-value"/> </xsl:template> <xsl:template name="write-member"> <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="$value" mode="json-value"/> </xsl:template> <xsl:template name="write-member-string"> <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:call-template name="write-string"> <xsl:with-param name="text" select="$value"/> </xsl:call-template> </xsl:template> <xsl:template name="write-member-array"> <xsl:param name="name"/> <xsl:param name="values"/> <xsl:call-template name="write-string"> <xsl:with-param name="text" select="$name"/> </xsl:call-template> <xsl:text> : </xsl:text> <xsl:call-template name="write-array"> <xsl:with-param name="values" select="$values"/> </xsl:call-template> </xsl:template> <xsl:template name="write-separator"> <xsl:text>, </xsl:text> </xsl:template> <!-- specialized template traits --> <xsl:template name="write-string"> <xsl:param name="text"/> <xsl:text>"</xsl:text> <xsl:call-template name="escape-bs-string"> <xsl:with-param name="s" select="$text"/> </xsl:call-template> <xsl:text>"</xsl: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"/> <xsl:text> }</xsl:text> </xsl:template> <xsl:template name="write-array"> <xsl:param name="values"/> <xsl:text>[ </xsl:text> <xsl:apply-templates select="$values" mode="json-array-item"/> <xsl:text> ]</xsl:text> </xsl:template> <xsl:template name="write-members"> <xsl:param name="members" select="*"/> <xsl:for-each select="$members"> <xsl:variable name="current" select="."/> <xsl:variable name="values" select="$members[local-name(.) = local-name($current)]"/> <xsl:if test="generate-id($current) = generate-id($values)"> <xsl:if test="position()>1"> <xsl:call-template name="write-separator"/> </xsl:if> <xsl:apply-templates select="$current" mode="json-member"> <xsl:with-param name="values" select="$values"/> </xsl:apply-templates> </xsl:if> </xsl:for-each> </xsl:template> <!-- escape string --> <!-- Copyright (c) 2006,2008 Doeke Zanstra All rights reserved. https://github.com/doekman/xml2json-xslt/blob/master/xml2json.xslt --> <!-- Escape the backslash (\) before everything else. --> <xsl:template name="escape-bs-string"> <xsl:param name="s"/> <xsl:choose> <xsl:when test="contains($s,'\')"> <xsl:call-template name="escape-quot-string"> <xsl:with-param name="s" select="concat(substring-before($s,'\'),'\\')"/> </xsl:call-template> <xsl:call-template name="escape-bs-string"> <xsl:with-param name="s" select="substring-after($s,'\')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="escape-quot-string"> <xsl:with-param name="s" select="$s"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- Escape the double quote ("). --> <xsl:template name="escape-quot-string"> <xsl:param name="s"/> <xsl:choose> <xsl:when test="contains($s,'"')"> <xsl:call-template name="encode-string"> <xsl:with-param name="s" select="concat(substring-before($s,'"'),'\"')"/> </xsl:call-template> <xsl:call-template name="escape-quot-string"> <xsl:with-param name="s" select="substring-after($s,'"')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="encode-string"> <xsl:with-param name="s" select="$s"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- Replace tab, line feed and/or carriage return by its matching escape code. Can't escape backslash or double quote here, because they don't replace characters (� becomes \t), but they prefix characters (\ becomes \\). Besides, backslash should be seperate anyway, because it should be processed first. This function can't do that. --> <xsl:template name="encode-string"> <xsl:param name="s"/> <xsl:choose> <!-- tab --> <xsl:when test="contains($s,'	')"> <xsl:call-template name="encode-string"> <xsl:with-param name="s" select="concat(substring-before($s,'	'),'\t',substring-after($s,'	'))"/> </xsl:call-template> </xsl:when> <!-- line feed --> <xsl:when test="contains($s,'
')"> <xsl:call-template name="encode-string"> <xsl:with-param name="s" select="concat(substring-before($s,'
'),'\n',substring-after($s,'
'))"/> </xsl:call-template> </xsl:when> <!-- carriage return --> <xsl:when test="contains($s,'
')"> <xsl:call-template name="encode-string"> <xsl:with-param name="s" select="concat(substring-before($s,'
'),'\r',substring-after($s,'
'))"/> </xsl:call-template> </xsl:when> <xsl:otherwise><xsl:value-of select="$s"/></xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>