• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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', '/\*(.*?)\*/', '(''|&quot;)(([^\\]|\\[\\&quot;''/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>&#10;</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="\\([\\&quot;'/btnvfr])" flags="s">
39									<xsl:matching-substring>
40										<xsl:variable name="s" select="regex-group(1)"/>
41										<xsl:choose>
42											<xsl:when test="$s=('\', '&quot;', '''', '/')">
43												<xsl:value-of select="regex-group(1)"/>
44											</xsl:when>
45											<xsl:when test="$s='b'">
46												<!--xsl:text>&#8;</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>&#9;</xsl:text>
52											</xsl:when>
53											<xsl:when test="$s='n'">
54												<xsl:text>&#10;</xsl:text>
55											</xsl:when>
56											<xsl:when test="$s='v'">
57												<!--xsl:text>&#11;</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>&#12;</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>&#13;</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>