1<?xml version="1.0" encoding="utf-8"?> 2<!-- Downloaded on 12/6/2012 from http://www.gerixsoft.com/blog/xslt/json2xml --> 3 4<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 5 6 <xsl:template match="json"> 7 <xsl:copy> 8 <xsl:copy-of select="@*"/> 9 <xsl:call-template name="json2xml"> 10 <xsl:with-param name="text" select="."/> 11 </xsl:call-template> 12 </xsl:copy> 13 </xsl:template> 14 15 <xsl:template name="json2xml"> 16 <xsl:param name="text"/> 17 <xsl:variable name="mode0"> 18 <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)'"/> 19 <xsl:analyze-string select="$text" regex="{string-join($regexps,'|')}" flags="s"> 20 <xsl:matching-substring> 21 <xsl:choose> 22 <!-- single line comment --> 23 <xsl:when test="regex-group(1)"> 24 <xsl:comment> 25 <xsl:value-of select="regex-group(1)"/> 26 </xsl:comment> 27 <xsl:text> </xsl:text> 28 </xsl:when> 29 <!-- multi line comment --> 30 <xsl:when test="regex-group(2)"> 31 <xsl:comment> 32 <xsl:value-of select="regex-group(2)"/> 33 </xsl:comment> 34 </xsl:when> 35 <!-- string --> 36 <xsl:when test="regex-group(3)"> 37 <string> 38 <xsl:analyze-string select="regex-group(4)" regex="\\([\\"'/btnvfr])" flags="s"> 39 <xsl:matching-substring> 40 <xsl:variable name="s" select="regex-group(1)"/> 41 <xsl:choose> 42 <xsl:when test="$s=('\', '"', '''', '/')"> 43 <xsl:value-of select="regex-group(1)"/> 44 </xsl:when> 45 <xsl:when test="$s='b'"> 46 <!--xsl:text></xsl:text--> 47 <xsl:message select="'escape sequense \b is not supported by XML'"/> 48 <xsl:text>\b</xsl:text> 49 </xsl:when> 50 <xsl:when test="$s='t'"> 51 <xsl:text>	</xsl:text> 52 </xsl:when> 53 <xsl:when test="$s='n'"> 54 <xsl:text> </xsl:text> 55 </xsl:when> 56 <xsl:when test="$s='v'"> 57 <!--xsl:text></xsl:text--> 58 <xsl:message select="'escape sequence \v is not supported by XML'"/> 59 <xsl:text>\v</xsl:text> 60 </xsl:when> 61 <xsl:when test="$s='f'"> 62 <!--xsl:text></xsl:text--> 63 <xsl:message select="'escape sequence \f is not supported by XML'"/> 64 <xsl:text>\f</xsl:text> 65 </xsl:when> 66 <xsl:when test="$s='r'"> 67 <xsl:text> </xsl:text> 68 </xsl:when> 69 <xsl:otherwise> 70 <xsl:message terminate="yes" select="'internal error'"/> 71 </xsl:otherwise> 72 </xsl:choose> 73 </xsl:matching-substring> 74 <xsl:non-matching-substring> 75 <xsl:value-of select="."/> 76 </xsl:non-matching-substring> 77 </xsl:analyze-string> 78 </string> 79 </xsl:when> 80 <!-- double --> 81 <xsl:when test="regex-group(6)"> 82 <double> 83 <xsl:value-of select="regex-group(6)"/> 84 </double> 85 </xsl:when> 86 <!-- integer --> 87 <xsl:when test="regex-group(9)"> 88 <integer> 89 <xsl:value-of select="regex-group(9)"/> 90 </integer> 91 </xsl:when> 92 <!-- octal --> 93 <xsl:when test="regex-group(10)"> 94 <integer> 95 <xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(regex-group(10), 8)"/> 96 </integer> 97 </xsl:when> 98 <!-- hex --> 99 <xsl:when test="regex-group(11)"> 100 <integer> 101 <xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(replace(regex-group(11), '0x', ''), 16)"/> 102 </integer> 103 </xsl:when> 104 <!-- symbol --> 105 <xsl:when test="regex-group(12)"> 106 <symbol> 107 <xsl:value-of select="regex-group(12)"/> 108 </symbol> 109 </xsl:when> 110 <!-- boolean --> 111 <xsl:when test="regex-group(13)"> 112 <boolean> 113 <xsl:value-of select="regex-group(13)"/> 114 </boolean> 115 </xsl:when> 116 <!-- null --> 117 <xsl:when test="regex-group(14)"> 118 <null /> 119 </xsl:when> 120 <xsl:otherwise> 121 <xsl:message terminate="yes" select="'internal error'"/> 122 </xsl:otherwise> 123 </xsl:choose> 124 </xsl:matching-substring> 125 <xsl:non-matching-substring> 126 <xsl:if test="normalize-space()!=''"> 127 <xsl:message select="concat('unknown token: ', .)"/> 128 <xsl:value-of select="."/> 129 </xsl:if> 130 </xsl:non-matching-substring> 131 </xsl:analyze-string> 132 </xsl:variable> 133 <xsl:variable name="mode1"> 134 <xsl:apply-templates mode="json2xml1" select="$mode0/node()[1]"/> 135 </xsl:variable> 136 <xsl:variable name="mode2"> 137 <xsl:apply-templates mode="json2xml2" select="$mode1"/> 138 </xsl:variable> 139 <xsl:variable name="mode3"> 140 <xsl:apply-templates mode="json2xml3" select="$mode2"/> 141 </xsl:variable> 142 <xsl:copy-of select="$mode3"/> <!-- change $mode3 to $mode[0-2] for easy debug --> 143 </xsl:template> 144 145 <!-- json2xml1 mode: group content between {} and [] into object and array elements --> 146 147 <xsl:template mode="json2xml1" match="node()" priority="-9"> 148 <xsl:copy-of select="."/> 149 <xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/> 150 </xsl:template> 151 152 <xsl:template mode="json2xml1" match="symbol[.=('}',']')]"/> 153 154 <xsl:template mode="json2xml1" match="symbol[.=('{','[')]"> 155 <xsl:element name="{if (.='{') then 'object' else 'array'}"> 156 <xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/> 157 </xsl:element> 158 <xsl:variable name="level" select="count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])+1"/> 159 <xsl:variable name="ender" 160 select="following-sibling::symbol[.=('}',']') and count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])=$level][1]"/> 161 <xsl:apply-templates mode="json2xml1" select="$ender/following-sibling::node()[1]"/> 162 </xsl:template> 163 164 <!-- json2xml2 mode: group <string>:<string|integer|double|object|array> into field element --> 165 166 <xsl:template priority="-9" mode="json2xml2" match="@*|node()"> 167 <xsl:copy> 168 <xsl:apply-templates mode="json2xml2" select="@*|node()"/> 169 </xsl:copy> 170 </xsl:template> 171 172 <xsl:template mode="json2xml2" 173 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)]"/> 174 175 <xsl:template mode="json2xml2" 176 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)]"> 177 <field name="{preceding-sibling::*[1]}"> 178 <xsl:for-each select="following-sibling::*[1]"> 179 <xsl:copy> 180 <xsl:apply-templates mode="json2xml2" select="@*|node()"/> 181 </xsl:copy> 182 </xsl:for-each> 183 </field> 184 </xsl:template> 185 186 <xsl:template mode="json2xml2" 187 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[.=':']]"/> 188 189 <!-- json2xml3 mode: drop comma between consecutive field and object elements --> 190 191 <xsl:template priority="-9" mode="json2xml3" match="@*|node()"> 192 <xsl:copy> 193 <xsl:apply-templates mode="json2xml3" select="@*|node()"/> 194 </xsl:copy> 195 </xsl:template> 196 197 <xsl:template mode="json2xml3" match="object/symbol[.=','][preceding-sibling::*[1]/self::field and following-sibling::*[1]/self::field]"/> 198 199 <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)]"/> 200 201</xsl:stylesheet>