Imported Upstream version 0.17
[liburi-template-perl.git] / t / cases / json2xml.xslt
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>