You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
7.8 KiB
201 lines
7.8 KiB
<?xml version="1.0" encoding="utf-8"?> |
|
<!-- Downloaded on 12/6/2012 from http://www.gerixsoft.com/blog/xslt/json2xml --> |
|
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
|
|
|
<xsl:template match="json"> |
|
<xsl:copy> |
|
<xsl:copy-of select="@*"/> |
|
<xsl:call-template name="json2xml"> |
|
<xsl:with-param name="text" select="."/> |
|
</xsl:call-template> |
|
</xsl:copy> |
|
</xsl:template> |
|
|
|
<xsl:template name="json2xml"> |
|
<xsl:param name="text"/> |
|
<xsl:variable name="mode0"> |
|
<xsl:variable name="regexps" select="'//(.*?)\n', '/\*(.*?)\*/', '(''|")(([^\\]|\\[\\"''/btnvfr])*?)\3', '(-?\d+(\.\d+([eE][+-]?\d+)?|[eE][+-]?\d+))', '(-?[1-9]\d*)', '(-?0[0-7]+)', '(-?0x[0-9a-fA-F]+)', '([:,\{\}\[\]])', '(true|false)', '(null)'"/> |
|
<xsl:analyze-string select="$text" regex="{string-join($regexps,'|')}" flags="s"> |
|
<xsl:matching-substring> |
|
<xsl:choose> |
|
<!-- single line comment --> |
|
<xsl:when test="regex-group(1)"> |
|
<xsl:comment> |
|
<xsl:value-of select="regex-group(1)"/> |
|
</xsl:comment> |
|
<xsl:text> </xsl:text> |
|
</xsl:when> |
|
<!-- multi line comment --> |
|
<xsl:when test="regex-group(2)"> |
|
<xsl:comment> |
|
<xsl:value-of select="regex-group(2)"/> |
|
</xsl:comment> |
|
</xsl:when> |
|
<!-- string --> |
|
<xsl:when test="regex-group(3)"> |
|
<string> |
|
<xsl:analyze-string select="regex-group(4)" regex="\\([\\"'/btnvfr])" flags="s"> |
|
<xsl:matching-substring> |
|
<xsl:variable name="s" select="regex-group(1)"/> |
|
<xsl:choose> |
|
<xsl:when test="$s=('\', '"', '''', '/')"> |
|
<xsl:value-of select="regex-group(1)"/> |
|
</xsl:when> |
|
<xsl:when test="$s='b'"> |
|
<!--xsl:text></xsl:text--> |
|
<xsl:message select="'escape sequense \b is not supported by XML'"/> |
|
<xsl:text>\b</xsl:text> |
|
</xsl:when> |
|
<xsl:when test="$s='t'"> |
|
<xsl:text>	</xsl:text> |
|
</xsl:when> |
|
<xsl:when test="$s='n'"> |
|
<xsl:text> </xsl:text> |
|
</xsl:when> |
|
<xsl:when test="$s='v'"> |
|
<!--xsl:text></xsl:text--> |
|
<xsl:message select="'escape sequence \v is not supported by XML'"/> |
|
<xsl:text>\v</xsl:text> |
|
</xsl:when> |
|
<xsl:when test="$s='f'"> |
|
<!--xsl:text></xsl:text--> |
|
<xsl:message select="'escape sequence \f is not supported by XML'"/> |
|
<xsl:text>\f</xsl:text> |
|
</xsl:when> |
|
<xsl:when test="$s='r'"> |
|
<xsl:text> </xsl:text> |
|
</xsl:when> |
|
<xsl:otherwise> |
|
<xsl:message terminate="yes" select="'internal error'"/> |
|
</xsl:otherwise> |
|
</xsl:choose> |
|
</xsl:matching-substring> |
|
<xsl:non-matching-substring> |
|
<xsl:value-of select="."/> |
|
</xsl:non-matching-substring> |
|
</xsl:analyze-string> |
|
</string> |
|
</xsl:when> |
|
<!-- double --> |
|
<xsl:when test="regex-group(6)"> |
|
<double> |
|
<xsl:value-of select="regex-group(6)"/> |
|
</double> |
|
</xsl:when> |
|
<!-- integer --> |
|
<xsl:when test="regex-group(9)"> |
|
<integer> |
|
<xsl:value-of select="regex-group(9)"/> |
|
</integer> |
|
</xsl:when> |
|
<!-- octal --> |
|
<xsl:when test="regex-group(10)"> |
|
<integer> |
|
<xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(regex-group(10), 8)"/> |
|
</integer> |
|
</xsl:when> |
|
<!-- hex --> |
|
<xsl:when test="regex-group(11)"> |
|
<integer> |
|
<xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(replace(regex-group(11), '0x', ''), 16)"/> |
|
</integer> |
|
</xsl:when> |
|
<!-- symbol --> |
|
<xsl:when test="regex-group(12)"> |
|
<symbol> |
|
<xsl:value-of select="regex-group(12)"/> |
|
</symbol> |
|
</xsl:when> |
|
<!-- boolean --> |
|
<xsl:when test="regex-group(13)"> |
|
<boolean> |
|
<xsl:value-of select="regex-group(13)"/> |
|
</boolean> |
|
</xsl:when> |
|
<!-- null --> |
|
<xsl:when test="regex-group(14)"> |
|
<null /> |
|
</xsl:when> |
|
<xsl:otherwise> |
|
<xsl:message terminate="yes" select="'internal error'"/> |
|
</xsl:otherwise> |
|
</xsl:choose> |
|
</xsl:matching-substring> |
|
<xsl:non-matching-substring> |
|
<xsl:if test="normalize-space()!=''"> |
|
<xsl:message select="concat('unknown token: ', .)"/> |
|
<xsl:value-of select="."/> |
|
</xsl:if> |
|
</xsl:non-matching-substring> |
|
</xsl:analyze-string> |
|
</xsl:variable> |
|
<xsl:variable name="mode1"> |
|
<xsl:apply-templates mode="json2xml1" select="$mode0/node()[1]"/> |
|
</xsl:variable> |
|
<xsl:variable name="mode2"> |
|
<xsl:apply-templates mode="json2xml2" select="$mode1"/> |
|
</xsl:variable> |
|
<xsl:variable name="mode3"> |
|
<xsl:apply-templates mode="json2xml3" select="$mode2"/> |
|
</xsl:variable> |
|
<xsl:copy-of select="$mode3"/> <!-- change $mode3 to $mode[0-2] for easy debug --> |
|
</xsl:template> |
|
|
|
<!-- json2xml1 mode: group content between {} and [] into object and array elements --> |
|
|
|
<xsl:template mode="json2xml1" match="node()" priority="-9"> |
|
<xsl:copy-of select="."/> |
|
<xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/> |
|
</xsl:template> |
|
|
|
<xsl:template mode="json2xml1" match="symbol[.=('}',']')]"/> |
|
|
|
<xsl:template mode="json2xml1" match="symbol[.=('{','[')]"> |
|
<xsl:element name="{if (.='{') then 'object' else 'array'}"> |
|
<xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/> |
|
</xsl:element> |
|
<xsl:variable name="level" select="count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])+1"/> |
|
<xsl:variable name="ender" |
|
select="following-sibling::symbol[.=('}',']') and count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])=$level][1]"/> |
|
<xsl:apply-templates mode="json2xml1" select="$ender/following-sibling::node()[1]"/> |
|
</xsl:template> |
|
|
|
<!-- json2xml2 mode: group <string>:<string|integer|double|object|array> into field element --> |
|
|
|
<xsl:template priority="-9" mode="json2xml2" match="@*|node()"> |
|
<xsl:copy> |
|
<xsl:apply-templates mode="json2xml2" select="@*|node()"/> |
|
</xsl:copy> |
|
</xsl:template> |
|
|
|
<xsl:template mode="json2xml2" |
|
match="string[following-sibling::*[1]/self::symbol[.=':'] and following-sibling::*[2]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"/> |
|
|
|
<xsl:template mode="json2xml2" |
|
match="symbol[.=':'][preceding-sibling::*[1]/self::string and following-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"> |
|
<field name="{preceding-sibling::*[1]}"> |
|
<xsl:for-each select="following-sibling::*[1]"> |
|
<xsl:copy> |
|
<xsl:apply-templates mode="json2xml2" select="@*|node()"/> |
|
</xsl:copy> |
|
</xsl:for-each> |
|
</field> |
|
</xsl:template> |
|
|
|
<xsl:template mode="json2xml2" |
|
match="*[self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null][preceding-sibling::*[2]/self::string and preceding-sibling::*[1]/self::symbol[.=':']]"/> |
|
|
|
<!-- json2xml3 mode: drop comma between consecutive field and object elements --> |
|
|
|
<xsl:template priority="-9" mode="json2xml3" match="@*|node()"> |
|
<xsl:copy> |
|
<xsl:apply-templates mode="json2xml3" select="@*|node()"/> |
|
</xsl:copy> |
|
</xsl:template> |
|
|
|
<xsl:template mode="json2xml3" match="object/symbol[.=','][preceding-sibling::*[1]/self::field and following-sibling::*[1]/self::field]"/> |
|
|
|
<xsl:template mode="json2xml3" match="array/symbol[.=','][preceding-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null) and following-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"/> |
|
|
|
</xsl:stylesheet> |