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:when test="contains($s,'3&quot;')">
64
                <xsl:call-template name="encode-string">
65
                    <xsl:with-param name="s" select="concat(substring-before($s,'3&quot;'),'\3&quot;')"/>
66
                </xsl:call-template>
67
                <xsl:call-template name="escape-quot-string">
68
                    <xsl:with-param name="s" select="substring-after($s,'3&quot;')"/>
69
                </xsl:call-template>
70
            </xsl:when>
71
            <xsl:otherwise>
72
                <xsl:call-template name="encode-string">
73
                    <xsl:with-param name="s" select="$s"/>
74
                </xsl:call-template>
75
            </xsl:otherwise>
76
        </xsl:choose>
77
    </xsl:template>
78

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

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

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

    
221
    <!-- this template handles attribute nodes -->
222
    <xsl:template match="@*">
223
        <!-- attach prefix to attribute names -->
224
        <xsl:text>"@</xsl:text>
225
        <xsl:value-of select="name()"/>
226
        <xsl:text>" : </xsl:text>
227
        <xsl:variable name="t" select="." />
228
        <xsl:choose>
229
            <xsl:when test="translate($t, 'TRUE', 'true') = 'true'">
230
                <xsl:text>true</xsl:text>
231
            </xsl:when> 
232
            <xsl:when test="translate($t, 'FALSE', 'false') = 'false'">
233
                <xsl:text>false</xsl:text>
234
            </xsl:when>
235
            <xsl:otherwise>
236
                <xsl:text>"</xsl:text>
237
                <xsl:call-template name="escape-bs-string">
238
                    <xsl:with-param name="s" select="$t"/>
239
                </xsl:call-template>
240
                <xsl:text>"</xsl:text>
241
            </xsl:otherwise>
242
        </xsl:choose>
243
        <xsl:if test="position() != last()">
244
            <xsl:text>, </xsl:text>
245
        </xsl:if>
246
    </xsl:template>
247

    
248
</xsl:stylesheet>
(30-30/58)