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

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

    
205
    <!-- this template handles attribute nodes -->
206
    <xsl:template match="@*">
207
        <!-- attach prefix to attribute names -->
208
        <xsl:text>"@</xsl:text>
209
        <xsl:value-of select="name()"/>
210
        <xsl:text>" : </xsl:text>
211
        <xsl:variable name="t" select="." />
212
        <xsl:choose>
213
            <xsl:when test="translate($t, 'TRUE', 'true') = 'true'">
214
                <xsl:text>true</xsl:text>
215
            </xsl:when> 
216
            <xsl:when test="translate($t, 'FALSE', 'false') = 'false'">
217
                <xsl:text>false</xsl:text>
218
            </xsl:when>
219
            <xsl:otherwise>
220
                <xsl:text>"</xsl:text>
221
                <xsl:value-of select="$t"/>
222
                <xsl:text>"</xsl:text>
223
            </xsl:otherwise>
224
        </xsl:choose>
225
        <xsl:if test="position() != last()">
226
            <xsl:text>, </xsl:text>
227
        </xsl:if>
228
    </xsl:template>
229

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