Created
March 15, 2012 10:46
-
-
Save designermonkey/2043582 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<xsl:stylesheet version="1.0" | |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
xmlns:exsl="http://exslt.org/common" | |
extension-element-prefixes="exsl"> | |
<!-- | |
A complete XML to JSON transformation utility adapted from | |
Doeke Zanstra's xml2json utility (http://code.google.com/p/xml2json-xslt/) | |
--> | |
<xsl:strip-space elements="*"/> | |
<!-- | |
Example call | |
<xsl:call-template name="xml-to-json"> | |
<xsl:with-param name="xml"> | |
[Any XML or XSLT transformation] | |
</xsl:with-param> | |
</xsl:call-template> | |
--> | |
<xsl:template name="xml-to-json"> | |
<xsl:param name="xml" /> | |
<xsl:apply-templates select="exsl:node-set($xml)" mode="xml-to-json" /> | |
</xsl:template> | |
<!-- string --> | |
<xsl:template match="text()" mode="xml-to-json" > | |
<xsl:call-template name="escape-string"> | |
<xsl:with-param name="s" select="."/> | |
</xsl:call-template> | |
</xsl:template> | |
<!-- Main template for escaping strings; used by above template and for object-properties | |
Responsibilities: placed quotes around string, and chain up to next filter, escape-bs-string --> | |
<xsl:template name="escape-string"> | |
<xsl:param name="s"/> | |
<xsl:text>"</xsl:text> | |
<xsl:call-template name="escape-bs-string"> | |
<xsl:with-param name="s" select="$s"/> | |
</xsl:call-template> | |
<xsl:text>"</xsl:text> | |
</xsl:template> | |
<!-- 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> | |
<!-- number (no support for javascript mantise) --> | |
<xsl:template match="text()[not(string(number())='NaN')]" mode="xml-to-json" > | |
<xsl:choose> | |
<xsl:when test="starts-with(string(.), '0')"> | |
"<xsl:value-of select="string(.)"/>" | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:value-of select="string(.)"/> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:template> | |
<!-- boolean, case-insensitive --> | |
<xsl:template match="text()[translate(.,'TRUE','true')='true']" mode="xml-to-json" >true</xsl:template> | |
<xsl:template match="text()[translate(.,'FALSE','false')='false']" mode="xml-to-json" >false</xsl:template> | |
<!-- item:null --> | |
<xsl:template match="*[count(child::node())=0]" mode="xml-to-json" > | |
<xsl:call-template name="escape-string"> | |
<xsl:with-param name="s" select="local-name()"/> | |
</xsl:call-template> | |
<xsl:text>:null</xsl:text> | |
<xsl:if test="following-sibling::*">,</xsl:if> | |
</xsl:template> | |
<!-- object --> | |
<xsl:template match="*" mode="xml-to-json" > | |
<xsl:if test="not(preceding-sibling::*)">{</xsl:if> | |
<xsl:call-template name="escape-string"> | |
<xsl:with-param name="s" select="name()"/> | |
</xsl:call-template> | |
<xsl:text>:</xsl:text> | |
<xsl:apply-templates select="child::node()" mode="xml-to-json" /> | |
<xsl:if test="following-sibling::*">,</xsl:if> | |
<xsl:if test="not(following-sibling::*)">}</xsl:if> | |
</xsl:template> | |
<!-- array --> | |
<xsl:template match="*[count(../*[name(../*)=name(.)])=count(../*) and count(../*)>1]" mode="xml-to-json" > | |
<xsl:if test="not(preceding-sibling::*)">[</xsl:if> | |
<xsl:choose> | |
<xsl:when test="not(child::node())"> | |
<xsl:text>null</xsl:text> | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:apply-templates select="child::node()" mode="xml-to-json" /> | |
</xsl:otherwise> | |
</xsl:choose> | |
<xsl:if test="following-sibling::*">,</xsl:if> | |
<xsl:if test="not(following-sibling::*)">]</xsl:if> | |
</xsl:template> | |
</xsl:stylesheet> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment