xml-smart 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|