xml-smart 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +4 -0
- data/COPYING +504 -0
- data/README.rdoc +55 -0
- data/Rakefile +15 -0
- data/example/EXAMPLE.xml +18 -0
- data/example/xpath_visual.rb +54 -0
- data/lib/xml/XSDtoRNG.xsl +448 -0
- data/lib/xml/smart.rb +177 -0
- data/lib/xml/smart_dom.rb +118 -0
- data/lib/xml/smart_domattribute.rb +34 -0
- data/lib/xml/smart_domattributeset.rb +62 -0
- data/lib/xml/smart_domelement.rb +213 -0
- data/lib/xml/smart_domnamespace.rb +32 -0
- data/lib/xml/smart_domnamespaceset.rb +125 -0
- data/lib/xml/smart_domnodeset.rb +59 -0
- data/lib/xml/smart_domother.rb +16 -0
- data/lib/xml/smart_domtext.rb +25 -0
- data/lib/xml/smart_qname.rb +34 -0
- data/test/1.xml +1 -0
- data/test/2.xml +1 -0
- data/test/3.xml +1 -0
- data/test/EXAMPLE-NS.xml +18 -0
- data/test/EXAMPLE-NSE.xml +18 -0
- data/test/EXAMPLE.str.xml +6 -0
- data/test/EXAMPLE.str.xml.test +6 -0
- data/test/EXAMPLE.tmp.xml +4 -0
- data/test/EXAMPLE.tmp.xml.test +4 -0
- data/test/EXAMPLE.xml +17 -0
- data/test/HELLO-MORE.xml +1 -0
- data/test/HELLO.rng +9 -0
- data/test/HELLO.xml +8 -0
- data/test/HELLO.xsd +16 -0
- data/test/XSL_BASE.xml +17 -0
- data/test/XSL_BASE.xml.test +16 -0
- data/test/XSL_DOCUMENT.xml +48 -0
- data/test/concurrent.xml +1 -0
- data/test/smartrunner.rb +25 -0
- data/test/tc_add.rb +21 -0
- data/test/tc_basic.rb +108 -0
- data/test/tc_concurrent.rb +73 -0
- data/test/tc_copy.rb +41 -0
- data/test/tc_create.rb +32 -0
- data/test/tc_delete.rb +52 -0
- data/test/tc_move_elements.rb +24 -0
- data/test/tc_namespace_default.rb +70 -0
- data/test/tc_namespace_detailed.rb +44 -0
- data/test/tc_namespace_find.rb +22 -0
- data/test/tc_nested.rb +26 -0
- data/test/tc_qname.rb +30 -0
- data/test/tc_relaxng.rb +30 -0
- data/test/tc_set_or_replace.rb +57 -0
- data/test/tc_sort.rb +18 -0
- data/test/tc_string.rb +41 -0
- data/test/tc_todoc.rb +27 -0
- data/test/tc_write.rb +19 -0
- data/test/tc_xinclude.rb +26 -0
- data/test/tc_xmlschema.rb +30 -0
- data/test/tc_xpath.rb +16 -0
- data/test/tc_xpath_attrs.rb +24 -0
- data/test/tc_xpath_functions.rb +12 -0
- data/test/tc_xpath_root.rb +23 -0
- data/test/tc_xsl.rb +22 -0
- data/xml-smart.gemspec +26 -0
- metadata +201 -0
@@ -0,0 +1,448 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!--
|
3
|
+
Copyright or © or Copr. Nicolas Debeissat
|
4
|
+
|
5
|
+
nicolas.debeissat@gmail.com (http://debeissat.nicolas.free.fr/)
|
6
|
+
|
7
|
+
This software is a computer program whose purpose is to convert a
|
8
|
+
XSD schema into a RelaxNG schema.
|
9
|
+
|
10
|
+
This software is governed by the CeCILL license under French law and
|
11
|
+
abiding by the rules of distribution of free software. You can use,
|
12
|
+
modify and/ or redistribute the software under the terms of the CeCILL
|
13
|
+
license as circulated by CEA, CNRS and INRIA at the following URL
|
14
|
+
"http://www.cecill.info".
|
15
|
+
|
16
|
+
As a counterpart to the access to the source code and rights to copy,
|
17
|
+
modify and redistribute granted by the license, users are provided only
|
18
|
+
with a limited warranty and the software's author, the holder of the
|
19
|
+
economic rights, and the successive licensors have only limited
|
20
|
+
liability.
|
21
|
+
|
22
|
+
In this respect, the user's attention is drawn to the risks associated
|
23
|
+
with loading, using, modifying and/or developing or reproducing the
|
24
|
+
software by the user in light of its specific status of free software,
|
25
|
+
that may mean that it is complicated to manipulate, and that also
|
26
|
+
therefore means that it is reserved for developers and experienced
|
27
|
+
professionals having in-depth computer knowledge. Users are therefore
|
28
|
+
encouraged to load and test the software's suitability as regards their
|
29
|
+
requirements in conditions enabling the security of their systems and/or
|
30
|
+
data to be ensured and, more generally, to use and operate it in the
|
31
|
+
same conditions as regards security.
|
32
|
+
|
33
|
+
The fact that you are presently reading this means that you have had
|
34
|
+
knowledge of the CeCILL license and that you accept its terms.
|
35
|
+
|
36
|
+
-->
|
37
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:rng="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" exclude-result-prefixes="xs" version="1.0">
|
38
|
+
|
39
|
+
<xsl:output indent="yes" method="xml"/>
|
40
|
+
|
41
|
+
<xsl:preserve-space elements="*"/>
|
42
|
+
|
43
|
+
<xsl:template match="/xs:schema">
|
44
|
+
<rng:grammar>
|
45
|
+
<xsl:for-each select="namespace::*">
|
46
|
+
<xsl:if test="local-name() != 'xs'">
|
47
|
+
<xsl:copy/>
|
48
|
+
</xsl:if>
|
49
|
+
</xsl:for-each>
|
50
|
+
<xsl:attribute name="ns"><xsl:value-of select="@targetNamespace"/></xsl:attribute>
|
51
|
+
<xsl:attribute name="datatypeLibrary">http://www.w3.org/2001/XMLSchema-datatypes</xsl:attribute>
|
52
|
+
<xsl:apply-templates/>
|
53
|
+
</rng:grammar>
|
54
|
+
</xsl:template>
|
55
|
+
|
56
|
+
<!-- in order to manage occurrences (and defaut) attributes goes there
|
57
|
+
before going to mode="content" templates -->
|
58
|
+
<xsl:template match="xs:*">
|
59
|
+
<xsl:call-template name="occurrences"/>
|
60
|
+
</xsl:template>
|
61
|
+
|
62
|
+
<xsl:template match="comment()">
|
63
|
+
<xsl:copy/>
|
64
|
+
</xsl:template>
|
65
|
+
|
66
|
+
<!-- unique and key are not supported in RelaxNG, must be done in schematron -->
|
67
|
+
<xsl:template match="xs:unique|xs:key"/>
|
68
|
+
|
69
|
+
<xsl:template match="xs:annotation">
|
70
|
+
<a:documentation>
|
71
|
+
<xsl:apply-templates/>
|
72
|
+
</a:documentation>
|
73
|
+
</xsl:template>
|
74
|
+
|
75
|
+
<xsl:template match="xs:documentation">
|
76
|
+
<xsl:copy-of select="child::node()"/>
|
77
|
+
</xsl:template>
|
78
|
+
|
79
|
+
<xsl:template match="xs:appinfo">
|
80
|
+
<xsl:copy-of select="child::node()"/>
|
81
|
+
</xsl:template>
|
82
|
+
|
83
|
+
<xsl:template match="xs:union">
|
84
|
+
<rng:choice>
|
85
|
+
<xsl:apply-templates select="@memberTypes"/>
|
86
|
+
<xsl:apply-templates/>
|
87
|
+
</rng:choice>
|
88
|
+
</xsl:template>
|
89
|
+
|
90
|
+
<xsl:template match="@memberTypes">
|
91
|
+
<xsl:call-template name="declareMemberTypes">
|
92
|
+
<xsl:with-param name="memberTypes" select="."/>
|
93
|
+
</xsl:call-template>
|
94
|
+
</xsl:template>
|
95
|
+
|
96
|
+
<xsl:template match="xs:list">
|
97
|
+
<rng:list>
|
98
|
+
<xsl:apply-templates select="@itemType"/>
|
99
|
+
<xsl:apply-templates/>
|
100
|
+
</rng:list>
|
101
|
+
</xsl:template>
|
102
|
+
|
103
|
+
<xsl:template match="@itemType">
|
104
|
+
<xsl:call-template name="type">
|
105
|
+
<xsl:with-param name="type" select="."/>
|
106
|
+
</xsl:call-template>
|
107
|
+
</xsl:template>
|
108
|
+
|
109
|
+
<xsl:template match="xs:complexType[@name]|xs:simpleType[@name]|xs:group[@name]|xs:attributeGroup[@name]">
|
110
|
+
<!-- the schemas may be included several times, so it needs a combine attribute
|
111
|
+
(the attributes are inversed :-) at the transformation) -->
|
112
|
+
<rng:define name="{@name}">
|
113
|
+
<!-- work-around for empty issue -->
|
114
|
+
<xsl:choose>
|
115
|
+
<xsl:when test="not(*[local-name() != 'annotation'])">
|
116
|
+
<rng:empty/>
|
117
|
+
<xsl:apply-templates/>
|
118
|
+
</xsl:when>
|
119
|
+
<xsl:otherwise>
|
120
|
+
<xsl:apply-templates/>
|
121
|
+
</xsl:otherwise>
|
122
|
+
</xsl:choose>
|
123
|
+
</rng:define>
|
124
|
+
</xsl:template>
|
125
|
+
|
126
|
+
<!-- when finds a ref attribute replace it by its type call (ref name="" or type) -->
|
127
|
+
<xsl:template match="xs:*[@ref]" mode="content">
|
128
|
+
<!-- when finds a attribute declaraction with a ref attribute replace it by
|
129
|
+
its type call prefixed by attr_ -->
|
130
|
+
<xsl:choose>
|
131
|
+
<xsl:when test="local-name() = 'attribute'">
|
132
|
+
<xsl:variable name="type">
|
133
|
+
<xsl:choose>
|
134
|
+
<xsl:when test="contains(@ref, ':')">
|
135
|
+
<xsl:value-of select="concat('attr_', substring-after(@ref, ':'))"/>
|
136
|
+
</xsl:when>
|
137
|
+
<xsl:otherwise>
|
138
|
+
<xsl:value-of select="concat('attr_', @ref)"/>
|
139
|
+
</xsl:otherwise>
|
140
|
+
</xsl:choose>
|
141
|
+
</xsl:variable>
|
142
|
+
<xsl:call-template name="type">
|
143
|
+
<xsl:with-param name="type" select="$type"/>
|
144
|
+
</xsl:call-template>
|
145
|
+
</xsl:when>
|
146
|
+
<xsl:otherwise>
|
147
|
+
<xsl:call-template name="type">
|
148
|
+
<xsl:with-param name="type" select="@ref"/>
|
149
|
+
</xsl:call-template>
|
150
|
+
</xsl:otherwise>
|
151
|
+
</xsl:choose>
|
152
|
+
</xsl:template>
|
153
|
+
|
154
|
+
<!-- the <xs:simpleType> and <xs:complexType without name attribute are ignored -->
|
155
|
+
<xsl:template match="xs:sequence|xs:simpleContent|xs:complexContent|xs:simpleType|xs:complexType">
|
156
|
+
<xsl:apply-templates/>
|
157
|
+
</xsl:template>
|
158
|
+
|
159
|
+
<xsl:template match="xs:extension[@base]">
|
160
|
+
<xsl:call-template name="type">
|
161
|
+
<xsl:with-param name="type" select="@base"/>
|
162
|
+
</xsl:call-template>
|
163
|
+
</xsl:template>
|
164
|
+
|
165
|
+
<xsl:template match="xs:element[@name]">
|
166
|
+
<!-- case of root element -->
|
167
|
+
<xsl:choose>
|
168
|
+
<xsl:when test="parent::xs:schema">
|
169
|
+
<rng:start combine="choice">
|
170
|
+
<!-- must introduce prefix in order not to override a complextype of the same name -->
|
171
|
+
<rng:ref name="starting_{@name}"/>
|
172
|
+
</rng:start>
|
173
|
+
<rng:define name="starting_{@name}">
|
174
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
175
|
+
</rng:define>
|
176
|
+
</xsl:when>
|
177
|
+
<xsl:otherwise>
|
178
|
+
<xsl:call-template name="occurrences"/>
|
179
|
+
</xsl:otherwise>
|
180
|
+
</xsl:choose>
|
181
|
+
</xsl:template>
|
182
|
+
|
183
|
+
<xsl:template match="xs:restriction[@base]">
|
184
|
+
<xsl:choose>
|
185
|
+
<xsl:when test="xs:enumeration[@value]">
|
186
|
+
<rng:choice>
|
187
|
+
<xsl:apply-templates/>
|
188
|
+
</rng:choice>
|
189
|
+
</xsl:when>
|
190
|
+
<xsl:otherwise>
|
191
|
+
<xsl:call-template name="type">
|
192
|
+
<xsl:with-param name="type" select="@base"/>
|
193
|
+
</xsl:call-template>
|
194
|
+
</xsl:otherwise>
|
195
|
+
</xsl:choose>
|
196
|
+
</xsl:template>
|
197
|
+
|
198
|
+
<xsl:template match="xs:enumeration[@value]">
|
199
|
+
<rng:value>
|
200
|
+
<xsl:value-of select="@value"/>
|
201
|
+
</rng:value>
|
202
|
+
<xsl:apply-templates/>
|
203
|
+
</xsl:template>
|
204
|
+
|
205
|
+
<!--
|
206
|
+
support for fractionDigits, length, maxExclusive, maxInclusive, maxLength, minExclusive, minInclusive, minLength, pattern, totalDigits, whiteSpace
|
207
|
+
explicit removal of enumeration as not all the XSLT processor respect templates priority
|
208
|
+
-->
|
209
|
+
<xsl:template match="xs:*[not(self::xs:enumeration)][@value]">
|
210
|
+
<rng:param name="{local-name()}">
|
211
|
+
<xsl:value-of select="@value"/>
|
212
|
+
</rng:param>
|
213
|
+
</xsl:template>
|
214
|
+
|
215
|
+
<xsl:template match="xs:all">
|
216
|
+
<rng:interleave>
|
217
|
+
<xsl:for-each select="child::text()[normalize-space(.) != ''] | child::*">
|
218
|
+
<rng:optional>
|
219
|
+
<xsl:apply-templates select="current()"/>
|
220
|
+
</rng:optional>
|
221
|
+
</xsl:for-each>
|
222
|
+
</rng:interleave>
|
223
|
+
</xsl:template>
|
224
|
+
|
225
|
+
<xsl:template match="xs:import|xs:include|xs:redefine">
|
226
|
+
<rng:include>
|
227
|
+
<xsl:if test="@schemaLocation">
|
228
|
+
<xsl:attribute name="href"><xsl:value-of select="concat(substring-before(@schemaLocation, '.xsd'),'.rng')"/></xsl:attribute>
|
229
|
+
</xsl:if>
|
230
|
+
<xsl:if test="@namespace">
|
231
|
+
<xsl:attribute name="ns"><xsl:value-of select="@namespace"/></xsl:attribute>
|
232
|
+
</xsl:if>
|
233
|
+
<xsl:apply-templates/>
|
234
|
+
</rng:include>
|
235
|
+
</xsl:template>
|
236
|
+
|
237
|
+
<xsl:template match="@default">
|
238
|
+
<a:documentation>
|
239
|
+
default value is : <xsl:value-of select="."/>
|
240
|
+
</a:documentation>
|
241
|
+
</xsl:template>
|
242
|
+
|
243
|
+
<xsl:template match="xs:attribute[@name]">
|
244
|
+
<xsl:choose>
|
245
|
+
<!-- attributes specified at schema level -->
|
246
|
+
<xsl:when test="parent::xs:schema">
|
247
|
+
<rng:define name="attr_{@name}">
|
248
|
+
<xsl:apply-templates select="current()" mode="occurrences"/>
|
249
|
+
</rng:define>
|
250
|
+
</xsl:when>
|
251
|
+
<xsl:otherwise>
|
252
|
+
<xsl:apply-templates select="current()" mode="occurrences"/>
|
253
|
+
</xsl:otherwise>
|
254
|
+
</xsl:choose>
|
255
|
+
</xsl:template>
|
256
|
+
|
257
|
+
<xsl:template match="xs:attribute[@name]" mode="occurrences">
|
258
|
+
<xsl:choose>
|
259
|
+
<xsl:when test="@use and @use='prohibited'"/>
|
260
|
+
<xsl:when test="@use and @use='required'">
|
261
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
262
|
+
</xsl:when>
|
263
|
+
<!-- by default, attributes are optional -->
|
264
|
+
<xsl:otherwise>
|
265
|
+
<rng:optional>
|
266
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
267
|
+
</rng:optional>
|
268
|
+
</xsl:otherwise>
|
269
|
+
</xsl:choose>
|
270
|
+
</xsl:template>
|
271
|
+
|
272
|
+
<xsl:template match="xs:attribute[@name]" mode="content">
|
273
|
+
<rng:attribute name="{@name}">
|
274
|
+
<xsl:apply-templates select="@default" mode="attributeDefaultValue"/>
|
275
|
+
<!-- there can be no type attribute to <xs:attribute>, in this case, the type is defined in
|
276
|
+
a <xs:simpleType> or a <xs:complexType> inside -->
|
277
|
+
<xsl:choose>
|
278
|
+
<xsl:when test="@type">
|
279
|
+
<xsl:call-template name="type">
|
280
|
+
<xsl:with-param name="type" select="@type"/>
|
281
|
+
</xsl:call-template>
|
282
|
+
</xsl:when>
|
283
|
+
<xsl:otherwise>
|
284
|
+
<xsl:apply-templates/>
|
285
|
+
</xsl:otherwise>
|
286
|
+
</xsl:choose>
|
287
|
+
</rng:attribute>
|
288
|
+
</xsl:template>
|
289
|
+
|
290
|
+
<xsl:template match="@default" mode="attributeDefaultValue">
|
291
|
+
<xsl:attribute name="defaultValue" namespace="http://relaxng.org/ns/compatibility/annotations/1.0">
|
292
|
+
<xsl:value-of select="."/>
|
293
|
+
</xsl:attribute>
|
294
|
+
</xsl:template>
|
295
|
+
|
296
|
+
<xsl:template match="xs:any" mode="content">
|
297
|
+
<rng:element>
|
298
|
+
<rng:anyName/>
|
299
|
+
<rng:text/>
|
300
|
+
</rng:element>
|
301
|
+
</xsl:template>
|
302
|
+
|
303
|
+
<xsl:template match="xs:anyAttribute" mode="content">
|
304
|
+
<rng:attribute>
|
305
|
+
<rng:anyName/>
|
306
|
+
<rng:text/>
|
307
|
+
</rng:attribute>
|
308
|
+
</xsl:template>
|
309
|
+
|
310
|
+
<xsl:template match="xs:choice" mode="content">
|
311
|
+
<rng:choice>
|
312
|
+
<xsl:apply-templates/>
|
313
|
+
</rng:choice>
|
314
|
+
</xsl:template>
|
315
|
+
|
316
|
+
<xsl:template match="xs:element" mode="content">
|
317
|
+
<rng:element name="{@name}">
|
318
|
+
<xsl:choose>
|
319
|
+
<xsl:when test="@type">
|
320
|
+
<xsl:call-template name="type">
|
321
|
+
<xsl:with-param name="type" select="@type"/>
|
322
|
+
</xsl:call-template>
|
323
|
+
</xsl:when>
|
324
|
+
<!-- work-around for empty issue -->
|
325
|
+
<xsl:when test="not(*[local-name() != 'annotation']) and not(@type)">
|
326
|
+
<rng:empty/>
|
327
|
+
<xsl:apply-templates/>
|
328
|
+
</xsl:when>
|
329
|
+
<xsl:otherwise>
|
330
|
+
<xsl:apply-templates/>
|
331
|
+
</xsl:otherwise>
|
332
|
+
</xsl:choose>
|
333
|
+
</rng:element>
|
334
|
+
</xsl:template>
|
335
|
+
|
336
|
+
<xsl:template name="occurrences">
|
337
|
+
<xsl:apply-templates select="@default"/>
|
338
|
+
<xsl:choose>
|
339
|
+
<xsl:when test="@maxOccurs and @maxOccurs='unbounded'">
|
340
|
+
<xsl:choose>
|
341
|
+
<xsl:when test="@minOccurs and @minOccurs='0'">
|
342
|
+
<rng:zeroOrMore>
|
343
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
344
|
+
</rng:zeroOrMore>
|
345
|
+
</xsl:when>
|
346
|
+
<xsl:otherwise>
|
347
|
+
<rng:oneOrMore>
|
348
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
349
|
+
</rng:oneOrMore>
|
350
|
+
</xsl:otherwise>
|
351
|
+
</xsl:choose>
|
352
|
+
</xsl:when>
|
353
|
+
<xsl:when test="@minOccurs and @minOccurs='0'">
|
354
|
+
<rng:optional>
|
355
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
356
|
+
</rng:optional>
|
357
|
+
</xsl:when>
|
358
|
+
<!-- here minOccurs is present but not = 0 -->
|
359
|
+
<xsl:when test="@minOccurs">
|
360
|
+
<xsl:call-template name="loopUntilZero">
|
361
|
+
<xsl:with-param name="nbLoops" select="@minOccurs"/>
|
362
|
+
</xsl:call-template>
|
363
|
+
</xsl:when>
|
364
|
+
<xsl:otherwise>
|
365
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
366
|
+
</xsl:otherwise>
|
367
|
+
</xsl:choose>
|
368
|
+
</xsl:template>
|
369
|
+
|
370
|
+
<xsl:template name="loopUntilZero">
|
371
|
+
<xsl:param name="nbLoops"/>
|
372
|
+
<xsl:if test="$nbLoops > 0">
|
373
|
+
<xsl:apply-templates select="current()" mode="content"/>
|
374
|
+
<xsl:call-template name="loopUntilZero">
|
375
|
+
<xsl:with-param name="nbLoops" select="$nbLoops - 1"/>
|
376
|
+
</xsl:call-template>
|
377
|
+
</xsl:if>
|
378
|
+
</xsl:template>
|
379
|
+
|
380
|
+
<xsl:template name="type">
|
381
|
+
<xsl:param name="type"/>
|
382
|
+
<xsl:choose>
|
383
|
+
<xsl:when test="contains($type, 'anyType')">
|
384
|
+
<rng:data type="string">
|
385
|
+
<xsl:apply-templates/>
|
386
|
+
</rng:data>
|
387
|
+
</xsl:when>
|
388
|
+
<!-- have to improve the prefix detection -->
|
389
|
+
<xsl:when test="starts-with($type, 'xs:') or starts-with($type, 'xsd:')">
|
390
|
+
<rng:data type="{substring-after($type, ':')}">
|
391
|
+
<!-- xsltproc tries to apply templates on current attributes -->
|
392
|
+
<xsl:apply-templates select="*"/>
|
393
|
+
</rng:data>
|
394
|
+
</xsl:when>
|
395
|
+
<xsl:when test="starts-with($type, 'xml:')">
|
396
|
+
<xsl:variable name="localName" select="substring-after($type, ':')"/>
|
397
|
+
<rng:attribute name="{$localName}" ns="http://www.w3.org/XML/1998/namespace">
|
398
|
+
<xsl:choose>
|
399
|
+
<xsl:when test="$localName='lang'">
|
400
|
+
<rng:value type="language"/>
|
401
|
+
</xsl:when>
|
402
|
+
<xsl:when test="$localName='space'">
|
403
|
+
<rng:choice>
|
404
|
+
<rng:value>default</rng:value>
|
405
|
+
<rng:value>preserve</rng:value>
|
406
|
+
</rng:choice>
|
407
|
+
</xsl:when>
|
408
|
+
<xsl:otherwise>
|
409
|
+
<rng:text/>
|
410
|
+
</xsl:otherwise>
|
411
|
+
</xsl:choose>
|
412
|
+
</rng:attribute>
|
413
|
+
</xsl:when>
|
414
|
+
<xsl:otherwise>
|
415
|
+
<xsl:choose>
|
416
|
+
<xsl:when test="contains($type, ':')">
|
417
|
+
<rng:ref name="{substring-after($type, ':')}"/>
|
418
|
+
<xsl:apply-templates/>
|
419
|
+
</xsl:when>
|
420
|
+
<xsl:otherwise>
|
421
|
+
<rng:ref name="{$type}"/>
|
422
|
+
<xsl:apply-templates/>
|
423
|
+
</xsl:otherwise>
|
424
|
+
</xsl:choose>
|
425
|
+
</xsl:otherwise>
|
426
|
+
</xsl:choose>
|
427
|
+
</xsl:template>
|
428
|
+
|
429
|
+
<xsl:template name="declareMemberTypes">
|
430
|
+
<xsl:param name="memberTypes"/>
|
431
|
+
<xsl:choose>
|
432
|
+
<xsl:when test="contains($memberTypes, ' ')">
|
433
|
+
<xsl:call-template name="type">
|
434
|
+
<xsl:with-param name="type" select="substring-before($memberTypes, ' ')"/>
|
435
|
+
</xsl:call-template>
|
436
|
+
<xsl:call-template name="declareMemberTypes">
|
437
|
+
<xsl:with-param name="memberTypes" select="substring-after($memberTypes, ' ')"/>
|
438
|
+
</xsl:call-template>
|
439
|
+
</xsl:when>
|
440
|
+
<xsl:otherwise>
|
441
|
+
<xsl:call-template name="type">
|
442
|
+
<xsl:with-param name="type" select="$memberTypes"/>
|
443
|
+
</xsl:call-template>
|
444
|
+
</xsl:otherwise>
|
445
|
+
</xsl:choose>
|
446
|
+
</xsl:template>
|
447
|
+
|
448
|
+
</xsl:stylesheet>
|
data/lib/xml/smart.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'lockfile'
|
4
|
+
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_qname')
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_dom')
|
7
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domelement')
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domnodeset')
|
9
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domtext')
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domother')
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domattributeset')
|
12
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domattribute')
|
13
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domnamespaceset')
|
14
|
+
require File.expand_path(File.dirname(__FILE__) + '/smart_domnamespace')
|
15
|
+
|
16
|
+
module Nokogiri
|
17
|
+
module XML
|
18
|
+
class Document
|
19
|
+
def ns_counter
|
20
|
+
@ns_counter ||= 1
|
21
|
+
end
|
22
|
+
def ns_update
|
23
|
+
@ns_counter ||= 1
|
24
|
+
@ns_counter += 1
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def custom_namespace_prefixes_update
|
29
|
+
result = {}
|
30
|
+
|
31
|
+
diffs = []
|
32
|
+
ns = self.xpath('//namespace::*').to_a.delete_if do |n|
|
33
|
+
if diffs.include? n.href
|
34
|
+
true
|
35
|
+
else
|
36
|
+
diffs.push(n.href).uniq!
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
de = ns.find_all{|n| n.prefix.nil?}
|
42
|
+
if de.length == 1
|
43
|
+
result['xmlns'] = de[0].href
|
44
|
+
end
|
45
|
+
if de.length > 1
|
46
|
+
i = 0
|
47
|
+
de.each do |n|
|
48
|
+
unless result.has_value? n.href
|
49
|
+
result["xmlns#{i}"] = n.href
|
50
|
+
i += 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ns.find_all{|n| !n.prefix.nil? && !(n.prefix == 'xml')}.each do |n|
|
56
|
+
result[n.prefix] = n.href
|
57
|
+
end
|
58
|
+
@custom_namespace_prefixes = result
|
59
|
+
end
|
60
|
+
def custom_namespace_prefixes
|
61
|
+
@custom_namespace_prefixes || custom_namespace_prefixes_update
|
62
|
+
end
|
63
|
+
def user_custom_namespace_prefixes
|
64
|
+
@user_custom_namespace_prefixes ||= {}
|
65
|
+
end
|
66
|
+
def user_custom_namespace_prefixes=(h)
|
67
|
+
@user_custom_namespace_prefixes = h
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Node
|
72
|
+
def xpath_plain(path)
|
73
|
+
XPathContext.new(self).evaluate(path)
|
74
|
+
end
|
75
|
+
def xpath_fast(path)
|
76
|
+
return xpath(path,self.document.custom_namespace_prefixes.merge(self.document.user_custom_namespace_prefixes))
|
77
|
+
return NodeSet.new(document) unless document
|
78
|
+
@nsc ||= 0
|
79
|
+
if @nsc != self.document.ns_counter
|
80
|
+
@ctx = XPathContext.new(self)
|
81
|
+
@ctx.register_namespaces(self.document.custom_namespace_prefixes.merge(self.document.user_custom_namespace_prefixes))
|
82
|
+
@nsc = self.document.ns_counter
|
83
|
+
end
|
84
|
+
path = path.gsub(/xmlns:/, ' :') unless Nokogiri.uses_libxml?
|
85
|
+
@ctx.evaluate(path)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module XML
|
92
|
+
VERSION = '0.3.0'
|
93
|
+
LIBXML_VERSION = Nokogiri::VERSION_INFO['libxml']['loaded']
|
94
|
+
LOCKFILE = {
|
95
|
+
:min_sleep => 0.25,
|
96
|
+
:max_sleep => 5,
|
97
|
+
:sleep_inc => 0.25,
|
98
|
+
:max_age => 5
|
99
|
+
}
|
100
|
+
|
101
|
+
module Smart
|
102
|
+
COPY = 0
|
103
|
+
MOVE = 1
|
104
|
+
|
105
|
+
def initialize(name,default=nil); open(name,default); end
|
106
|
+
|
107
|
+
def self::modify(name,default=nil,&block)
|
108
|
+
raise Error, 'first parameter has to be a filename or filehandle' unless name.is_a?(String) || name.is_a?(IO)
|
109
|
+
raise Error, 'a block is mandatory' unless block_given?
|
110
|
+
lfname = name.is_a?(String) ? name : name.fileno.to_s
|
111
|
+
lockfile = Lockfile.new(lfname + '.lock',LOCKFILE)
|
112
|
+
begin
|
113
|
+
lockfile.lock
|
114
|
+
so = Smart::open_unprotected(name,default)
|
115
|
+
block.call(so)
|
116
|
+
so.save_as(name)
|
117
|
+
ensure
|
118
|
+
lockfile.unlock
|
119
|
+
end
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
def self::open(name,default=nil)
|
124
|
+
raise Error, 'first parameter has to be a filename or filehandle' unless name.is_a?(String) || name.is_a?(IO)
|
125
|
+
raise Error, 'second parameter has to be an xml string' unless default.is_a?(String) || default.nil?
|
126
|
+
lfname = name.is_a?(String) ? name : name.fileno.to_s
|
127
|
+
lockfile = Lockfile.new(lfname + '.lock',LOCKFILE)
|
128
|
+
dom = nil
|
129
|
+
begin
|
130
|
+
lockfile.lock
|
131
|
+
dom = Smart::open_unprotected(name,default)
|
132
|
+
ensure
|
133
|
+
lockfile.unlock
|
134
|
+
end
|
135
|
+
if dom && block_given?
|
136
|
+
yield dom
|
137
|
+
nil
|
138
|
+
else
|
139
|
+
dom
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def self::open_unprotected(name,default=nil)
|
144
|
+
raise Error, 'first parameter has to be a filename or filehandle' unless name.is_a?(String) || name.is_a?(IO)
|
145
|
+
raise Error, 'second parameter has to be an xml string' unless default.is_a?(String) || default.nil?
|
146
|
+
dom = begin
|
147
|
+
io = name.is_a?(String) ? ::Kernel::open(name) : name
|
148
|
+
Dom.new Nokogiri::XML::parse(io){|config| config.noblanks.noent.nsclean.strict }
|
149
|
+
rescue
|
150
|
+
if default.nil?
|
151
|
+
raise Error, "could not open #{name}"
|
152
|
+
else
|
153
|
+
Smart::string(default)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
if block_given?
|
157
|
+
yield dom
|
158
|
+
nil
|
159
|
+
else
|
160
|
+
dom
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def self::string(str)
|
165
|
+
raise Error, 'first parameter has to be stringable (:to_s)' unless str.is_a?(String)
|
166
|
+
dom = Dom.new Nokogiri::XML::parse(str.to_s){|config| config.noblanks.noent.nsclean.strict }
|
167
|
+
if block_given?
|
168
|
+
yield dom
|
169
|
+
nil
|
170
|
+
else
|
171
|
+
dom
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class Error < RuntimeError; end
|
176
|
+
end
|
177
|
+
end
|