Project

General

Profile

1
<?xml version="1.0" encoding="UTF-8"?>
2
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
3

    
4
    <!-- Turn off auto-insertion of <?xml> tag and set indenting on -->
5
    <xsl:output method="text" encoding="utf-8" indent="yes"/>
6

    
7
    <!-- strip whitespace from whitespace-only nodes -->
8
    <xsl:strip-space elements="*"/>
9

    
10
    <!-- create a key for every element in the document using its name -->
11
    <xsl:key name="names" match="*" use="concat(generate-id(..),'/',name())"/>
12

    
13
    <!-- start with the root element -->
14
    <xsl:template match="/">
15
        <!-- first element needs brackets around it as template does not do that -->
16
        <xsl:text>{ </xsl:text>
17
        <!-- call the template for elements using one unique name at a time -->
18
        <xsl:apply-templates select="*[generate-id(.) = generate-id(key('names', concat(generate-id(..),'/',name()))[1])]" >
19
            <xsl:sort select="name()" data-type="number"/>
20
        </xsl:apply-templates>
21
        <xsl:text> }</xsl:text>
22
    </xsl:template>
23

    
24
    <xsl:template name="escape-string">
25
        <xsl:param name="s"/>
26
        <xsl:text>"</xsl:text>
27
        <xsl:call-template name="escape-bs-string">
28
            <xsl:with-param name="s" select="$s"/>
29
        </xsl:call-template>
30
        <xsl:text>"</xsl:text>
31
    </xsl:template>
32

    
33
    <xsl:template name="escape-bs-string">
34
        <xsl:param name="s"/>
35
        <xsl:choose>
36
            <xsl:when test="contains($s,'\')">
37
                <xsl:call-template name="escape-quot-string">
38
                    <xsl:with-param name="s" select="concat(substring-before($s,'\'),'\\')"/>
39
                </xsl:call-template>
40
                <xsl:call-template name="escape-bs-string">
41
                    <xsl:with-param name="s" select="substring-after($s,'\')"/>
42
                </xsl:call-template>
43
            </xsl:when>
44
            <xsl:otherwise>
45
                <xsl:call-template name="escape-quot-string">
46
                    <xsl:with-param name="s" select="$s"/>
47
                </xsl:call-template>
48
            </xsl:otherwise>
49
        </xsl:choose>
50
    </xsl:template>
51

    
52
    <xsl:template name="escape-quot-string">
53
        <xsl:param name="s"/>
54
        <xsl:choose>
55
            <xsl:when test="contains($s,'&quot;')">
56
                <xsl:call-template name="encode-string">
57
                    <xsl:with-param name="s" select="concat(substring-before($s,'&quot;'),'\&quot;')"/>
58
                </xsl:call-template>
59
                <xsl:call-template name="escape-quot-string">
60
                    <xsl:with-param name="s" select="substring-after($s,'&quot;')"/>
61
                </xsl:call-template>
62
            </xsl:when>
63
            <xsl:otherwise>
64
                <xsl:call-template name="encode-string">
65
                    <xsl:with-param name="s" select="$s"/>
66
                </xsl:call-template>
67
            </xsl:otherwise>
68
        </xsl:choose>
69
    </xsl:template>
70

    
71
    <xsl:template name="encode-string">
72
        <xsl:param name="s"/>
73
        <xsl:choose>
74
            <!-- tab -->
75
            <xsl:when test="contains($s,'&#x9;')">
76
                <xsl:call-template name="encode-string">
77
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#x9;'),'\t',substring-after($s,'&#x9;'))"/>
78
                </xsl:call-template>
79
            </xsl:when>
80
            <!-- line feed -->
81
            <xsl:when test="contains($s,'&#xA;')">
82
                <xsl:call-template name="encode-string">
83
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#xA;'),'\n',substring-after($s,'&#xA;'))"/>
84
                </xsl:call-template>
85
            </xsl:when>
86
            <!-- carriage return -->
87
            <xsl:when test="contains($s,'&#xD;')">
88
                <xsl:call-template name="encode-string">
89
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#xD;'),'\r',substring-after($s,'&#xD;'))"/>
90
                </xsl:call-template>
91
            </xsl:when>
92
            <xsl:otherwise><xsl:value-of select="$s"/></xsl:otherwise>
93
        </xsl:choose>
94
    </xsl:template>
95

    
96
    <!-- this template handles elements -->
97
    <xsl:template match="*">
98
        <!-- count the number of elements with the same name -->
99
        <xsl:variable name="kctr" select="count(key('names', concat(generate-id(..),'/',name())))"/>
100
        <!-- iterate through by sets of elements with same name -->
101
        <xsl:for-each select="key('names', concat(generate-id(..),'/',name()))">
102
            <!-- deal with the element name and start of multiple element block -->
103
            <xsl:choose>
104
                <xsl:when test="($kctr > 1) and (position() = 1)">
105
                    <xsl:text>"</xsl:text>
106
                    <xsl:value-of select="name()"/>
107
                    <xsl:text>" : [ </xsl:text>
108
                </xsl:when>
109
                <xsl:when test="$kctr = 1 and name()!='result'">
110
                    <xsl:text>"</xsl:text>
111
                    <xsl:value-of select="name()"/>
112
                    <xsl:text>" : </xsl:text>
113
                </xsl:when>
114
                <xsl:when test="$kctr = 1 and name()='result'">
115
                    <xsl:text>"</xsl:text>
116
                    <xsl:value-of select="name()"/>
117
                    <xsl:text>" : [</xsl:text>
118
                </xsl:when>
119
            </xsl:choose>
120
            <!-- count number of elements, text nodes and attribute nodes -->
121
            <xsl:variable name="nctr" select="count(*|text()|@*)"/>
122
            <xsl:choose>
123
                <xsl:when test="$nctr = 0">
124
                    <!-- no contents at all -->
125
                    <xsl:text>null</xsl:text>
126
                </xsl:when>
127
                <xsl:otherwise>
128
                    <xsl:variable name="ctr" select="count(*)"/>
129
                    <xsl:variable name="tctr" select="count(text())"/>
130
                    <xsl:variable name="actr" select="count(@*)"/>
131
                    <!-- there will be contents so start an object -->
132
                    <xsl:text>{ </xsl:text>
133
                    <!-- handle attribute nodes -->
134
                    <xsl:if test="$actr > 0">
135
                        <xsl:apply-templates select="@*"/>
136
                        <xsl:if test="($tctr > 0) or ($ctr > 0)">
137
                            <xsl:text>, </xsl:text>
138
                        </xsl:if>
139
                    </xsl:if>
140
                    <!-- call template for child elements one unique name at a time -->
141
                    <xsl:if test="$ctr > 0">
142
                        <xsl:apply-templates select="*[generate-id(.) = generate-id(key('names', concat(generate-id(..),'/',name()))[1])]">
143
                            <xsl:sort select="name()" data-type="number"/>
144
                        </xsl:apply-templates>
145
                        <xsl:if test="$tctr > 0">
146
                            <xsl:text>, </xsl:text>
147
                        </xsl:if>
148
                    </xsl:if>
149
                    <!-- handle text nodes -->
150
                    <xsl:choose>
151
                        <xsl:when test="$tctr = 1">
152
                            <xsl:text>"$" : </xsl:text>
153
                            <xsl:apply-templates select="text()"/>
154
                        </xsl:when>
155
                        <xsl:when test="$tctr > 1">
156
                            <xsl:text>"$" : [ </xsl:text>
157
                            <xsl:apply-templates select="text()"/>
158
                            <xsl:text> ]</xsl:text>
159
                        </xsl:when>
160
                    </xsl:choose>
161
                    <xsl:text> }</xsl:text>
162
                </xsl:otherwise>
163
            </xsl:choose>
164
            <!-- special processing if we are in multiple element block -->
165
            <xsl:if test="$kctr > 1">
166
                <xsl:choose>
167
                    <xsl:when test="position() = last()">
168
                        <xsl:text> ]</xsl:text>
169
                    </xsl:when>
170
                    <xsl:otherwise>
171
                        <xsl:text>, </xsl:text>
172
                    </xsl:otherwise>
173
                </xsl:choose>
174
            </xsl:if>
175
            <xsl:if test="$kctr = 1 and name()='result'">
176
                <xsl:text> ]</xsl:text>
177
            </xsl:if>
178
        </xsl:for-each>
179
        <xsl:if test="position() != last()">
180
            <xsl:text>, </xsl:text>
181
        </xsl:if>
182
    </xsl:template>
183

    
184
    <!-- this template handle text nodes -->
185
    <xsl:template match="text()">
186
        <xsl:variable name="t" select="." />
187
        <xsl:choose>
188
            <!-- test to see if it is a number -->
189
            <xsl:when test="string(number($t)) != 'NaN' and not(starts-with($t,'+')) and (not(local-name(..)='code') and not(local-name(..)='subject'))">
190
                <xsl:value-of select="$t"/>
191
            </xsl:when>
192
            <!-- deal with any case booleans -->
193
            <xsl:when test="translate($t, 'TRUE', 'true') = 'true'">
194
                <xsl:text>true</xsl:text>
195
            </xsl:when>
196
            <xsl:when test="translate($t, 'FALSE', 'false') = 'false'">
197
                <xsl:text>false</xsl:text>
198
            </xsl:when>
199
            <!-- must be text -->
200
            <xsl:otherwise>
201
                <xsl:text>"</xsl:text>
202
                <xsl:call-template name="escape-bs-string">
203
                    <xsl:with-param name="s" select="$t"/>
204
                </xsl:call-template>
205
                <xsl:text>"</xsl:text>
206
            </xsl:otherwise>
207
        </xsl:choose>
208
        <xsl:if test="position() != last()">
209
            <xsl:text>, </xsl:text>
210
        </xsl:if>
211
    </xsl:template>
212

    
213
    <!-- this template handles attribute nodes -->
214
    <xsl:template match="@*">
215
        <!-- attach prefix to attribute names -->
216
        <xsl:text>"@</xsl:text>
217
        <xsl:value-of select="name()"/>
218
        <xsl:text>" : </xsl:text>
219
        <xsl:variable name="t" select="." />
220
        <xsl:choose>
221
            <xsl:when test="translate($t, 'TRUE', 'true') = 'true'">
222
                <xsl:text>true</xsl:text>
223
            </xsl:when> 
224
            <xsl:when test="translate($t, 'FALSE', 'false') = 'false'">
225
                <xsl:text>false</xsl:text>
226
            </xsl:when>
227
            <xsl:otherwise>
228
                <xsl:text>"</xsl:text>
229
                <xsl:value-of select="$t"/>
230
                <xsl:text>"</xsl:text>
231
            </xsl:otherwise>
232
        </xsl:choose>
233
        <xsl:if test="position() != last()">
234
            <xsl:text>, </xsl:text>
235
        </xsl:if>
236
    </xsl:template>
237

    
238
</xsl:stylesheet>
(24-24/46)