source: metadata/trunk/toolkit/xslt/comp2schema-v2/comp2schema.xsl @ 1772

Last change on this file since 1772 was 1772, checked in by twagoo, 13 years ago

Made comp2schema.xsl compatible with current versions of Saxon-HE by removing
saxon:indent-spaces and saxon:next-in-chain attributes, which are propietary Saxon extensions.
By default, the resulting XSD will no longer have pretty indentation (which could even be
beneficial to the performance!).

(Note that the current version of the ComponentRegistry however sets these parameters anyway, which is ok since it uses Saxon-B.)

  • Property svn:executable set to *
  • Property svn:keywords set to
    Date
    Rev
File size: 16.7 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2
3<!--
4    $Rev: 1772 $
5    $Date: 2012-02-24 14:42:25 +0000 (Fri, 24 Feb 2012) $
6-->
7
8<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
9    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dcr="http://www.isocat.org/ns/dcr"
10    xmlns:ann="http://www.clarin.eu">
11   
12    <xsl:variable name="CMDVersion" select="'1.1'"/>
13
14    <xsl:strip-space elements="*"/>
15    <xsl:include href="comp2schema-header.xsl"/>
16    <xsl:include href="cleanup-xsd.xsl"/>
17    <!-- note: the automatic chaining with clean-xsd.xsl only works with the Saxon XSLT processor, otherwise you'll have to do this manually (or use e.g the Xalan pipeDocument tag) -->
18    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" />
19
20    <!-- Start includes -->
21
22    <!-- resolve includes -->
23    <xsl:template match="@*|node()" mode="include">
24        <xsl:copy>
25            <xsl:apply-templates select="@*|node()" mode="include"/>
26        </xsl:copy>
27    </xsl:template>
28
29    <xsl:template match="CMD_Component[@filename]" mode="include">
30        <!-- some of the outer CMD_Component attributes can overwrite the inner CMD_Component attributes -->
31        <xsl:variable name="outer-attr" select="@CardinalityMin|@CardinalityMax"/>
32        <xsl:for-each select="document(@filename)/CMD_ComponentSpec/CMD_Component">
33            <xsl:variable name="inner-attr" select="@*"/>
34            <xsl:copy>
35                <xsl:apply-templates select="$outer-attr" mode="include"/>
36                <xsl:apply-templates
37                    select="$inner-attr[not(node-name(.) = $outer-attr/node-name(.))]"
38                    mode="include"/>
39                <xsl:apply-templates select="node()" mode="include"/>
40            </xsl:copy>
41        </xsl:for-each>
42    </xsl:template>
43
44    <!-- Stop includes -->
45
46    <!-- main -->
47    <xsl:template match="/">
48        <!-- Resolve all includes -->
49        <xsl:variable name="tree">
50            <xsl:apply-templates mode="include"/>
51        </xsl:variable>
52        <!-- Process the complete tree -->
53        <xsl:variable name="schema">
54            <xsl:apply-templates select="$tree/*"/>
55        </xsl:variable>
56        <xsl:apply-templates select="$schema" mode="clean" />
57    </xsl:template>
58
59    <!-- generate XSD -->
60    <xsl:template match="/CMD_ComponentSpec">
61
62        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dcr="http://www.isocat.org/ns/dcr" xmlns:cmd="http://www.clarin.eu/cmd/" targetNamespace="http://www.clarin.eu/cmd/" elementFormDefault="qualified">
63
64            <!-- import this for the use of the xml:lang attribute -->
65            <xs:import namespace="http://www.w3.org/XML/1998/namespace"
66                schemaLocation="http://www.w3.org/2001/xml.xsd"/>
67
68
69            <!--  first create complex types for valueschemes (not inline) -->
70            <xsl:call-template name="CreateComplexTypes"/>
71
72            <!-- then create simple type for the ResourceProxy -->
73            <xsl:call-template name="PrintHeaderType"/>
74
75
76            <xs:element name="CMD">
77                <xs:complexType>
78                   
79                    <xs:sequence>
80
81                        <!-- Produce (fixed) header elements (description and resources)-->
82                        <xsl:call-template name="PrintHeader"/>
83
84                        <!-- Then generate the components -->
85                        <xs:element name="Components">
86
87                            <xs:complexType>
88                                <xs:sequence>
89                                    <!--Start with processing the root component once and then process everything else recursively-->
90                                    <xsl:apply-templates select="/CMD_ComponentSpec/CMD_Component"/>
91                                </xs:sequence>
92                            </xs:complexType>
93                        </xs:element>
94
95                        <!-- Generate the footer -->
96                    </xs:sequence>
97                   
98                    <!-- CMD version -->
99                    <xs:attribute name="CMDVersion" fixed="{$CMDVersion}" use="required"/>
100                   
101                </xs:complexType>
102            </xs:element>
103        </xs:schema>
104
105    </xsl:template>
106
107
108    <xsl:template name="CreateComplexTypes">
109        <xsl:apply-templates select="CMD_Component" mode="types"/>
110    </xsl:template>
111
112
113    <!-- Start types -->
114
115    <!-- skip all text nodes -->
116    <xsl:template match="text()" mode="types"/>
117
118    <!-- first pass: create the complex types on top of the resulting XSD -->
119    <!-- ignore when this ValueScheme is descendant of an Attribute as we do not allow CV-attributes in a CV-list -->
120    <xsl:template match="ValueScheme[not(../../Attribute)]" mode="types">
121
122        <!-- create a unique suffix (the path to the element) to ensure the unicity of the types to be created -->
123        <xsl:variable name="uniquePath">
124            <xsl:call-template name="printComponentId">
125                <!-- start from the CMD_Element above and go upwards in the tree -->
126                <xsl:with-param name="node" select=".."/>
127            </xsl:call-template>
128        </xsl:variable>
129
130        <!-- first auto-generate a name for the simpletype to be extended -->
131        <xs:simpleType name="simpletype{$uniquePath}">
132            <xs:restriction base="xs:string">
133                <xsl:apply-templates select="pattern"/>
134                <xsl:apply-templates select="enumeration"/>
135            </xs:restriction>
136        </xs:simpleType>
137
138        <!--  then auto-derive a complextype for the attributes -->
139        <xs:complexType name="complextype{$uniquePath}">
140            <xs:simpleContent>
141                <xs:extension base="cmd:simpletype{$uniquePath}">
142                    <!-- now look at the attribute list of the CMD_Element parent of this ValueScheme-->
143                    <xsl:apply-templates select="parent::node()/AttributeList/Attribute"/>
144                    <!--<xs:attribute name="attributeName" type="xs:anyURI"/>-->
145                </xs:extension>
146            </xs:simpleContent>
147        </xs:complexType>
148
149    </xsl:template>
150
151    <!-- Stop types -->
152
153    <!-- create a unique identifier from the current ValueScheme element -->
154    <xsl:template name="printComponentId">
155        <xsl:param name="node"/>
156        <xsl:text>-</xsl:text>
157
158        <xsl:choose>
159
160            <!-- deeper recursion needed -->
161            <xsl:when test="$node[not(@ComponentId)]">
162
163                <xsl:choose>
164                    <!-- element has name, add it to the type name and recurse upwards in the tree -->
165                    <xsl:when test="name($node) = 'CMD_Element'">
166                        <xsl:value-of select="$node/attribute::name"/>
167                    </xsl:when>
168                    <!-- "worst" case: embedded anonymous component without ComponentId: use the xpath -->
169                    <xsl:when test="name($node)  = 'CMD_Component'">
170                        <xsl:value-of select="count($node/preceding-sibling::*)"/>
171                    </xsl:when>
172                </xsl:choose>
173
174                <!-- recursive call -->
175                <xsl:call-template name="printComponentId">
176                    <xsl:with-param name="node" select="$node/.."/>
177                </xsl:call-template>
178
179            </xsl:when>
180
181            <!-- end of recursion: component has ComponentId -->
182            <xsl:otherwise>
183                <xsl:value-of select="replace($node/attribute::ComponentId, ':', '.')"/>
184            </xsl:otherwise>
185
186        </xsl:choose>
187
188    </xsl:template>
189
190
191
192    <!-- convert all components -->
193    <xsl:template match="CMD_Component">
194        <!--  use override values if specified in parent <CMD_Component filename=...> , otherwise use default cardinality for this component -->
195        <xsl:param name="MinOccurs" select="@CardinalityMin"/>
196        <xsl:param name="MaxOccurs" select="@CardinalityMax"/>
197
198        <xs:element name="{@name}">
199
200            <xsl:if test="$MinOccurs">
201                <xsl:attribute name="minOccurs">
202                    <xsl:value-of select="$MinOccurs"/>
203                </xsl:attribute>
204            </xsl:if>
205            <xsl:if test="$MaxOccurs">
206                <xsl:attribute name="maxOccurs">
207                    <xsl:value-of select="$MaxOccurs"/>
208                </xsl:attribute>
209            </xsl:if>
210            <!-- Add a dcr:datcat if a ConceptLink attribute is found -->
211            <xsl:apply-templates select="./@ConceptLink"/>
212
213            <xs:complexType>
214                <xs:sequence>
215                    <!-- process all elements at this level -->
216                    <xsl:apply-templates select="./CMD_Element"/>
217                    <!-- process all components at one level deeper (recursive call) -->
218                    <xsl:apply-templates select="./CMD_Component"/>
219                </xs:sequence>
220                <xs:attribute name="ref" type="xs:IDREFS"/>
221                <xsl:apply-templates select="./AttributeList/Attribute"/>
222                <xsl:if test="@ComponentId">
223                    <xs:attribute name="ComponentId" type="xs:anyURI" fixed="{@ComponentId}"/>
224                </xsl:if>
225            </xs:complexType>
226
227        </xs:element>
228
229    </xsl:template>
230
231    <!-- Process all CMD_Elements, its attributes and children -->
232
233    <!-- Highest complexity: both attributes and a valuescheme, link to the type we created during the preprocessing of the ValueScheme -->
234    <xsl:template match="CMD_Element[./AttributeList][./ValueScheme]" priority="3">
235        <xs:element name="{@name}">
236
237            <!-- process all Documentation and DisplayPriority attributes -->
238            <xsl:call-template name="annotations"/>
239
240            <xsl:apply-templates select="@ConceptLink"/>
241            <xsl:apply-templates select="@CardinalityMin"/>
242            <xsl:apply-templates select="@CardinalityMax"/>
243            <xsl:apply-templates select="ValueScheme"/>
244
245        </xs:element>
246    </xsl:template>
247
248    <!-- Medium complexity: attributes (or Multilingual field) but no valuescheme, can be arranged inline -->
249    <xsl:template match="CMD_Element[./AttributeList or ./@Multilingual]" priority="2">
250        <xs:element name="{@name}">
251
252            <xsl:apply-templates select="@Multilingual"/>
253            <xsl:apply-templates select="@ConceptLink"/>
254            <xsl:apply-templates select="@CardinalityMin"/>
255            <xsl:apply-templates select="@CardinalityMax"/>
256
257            <!-- process all Documentation and DisplayPriority attributes -->
258            <xsl:call-template name="annotations"/>
259
260            <!-- <xsl:apply-templates select= "and(not(@type) and @*)"/> -->
261            <xs:complexType>
262                <xs:simpleContent>
263                    <xs:extension base="{concat('xs:',@ValueScheme)}">
264                        <xsl:apply-templates select="./AttributeList/Attribute"/>
265                        <!-- temporarily disabled -->
266                        <xsl:if test="./@Multilingual='true'">
267                            <xs:attribute ref="xml:lang" />
268                        </xsl:if>
269                    </xs:extension>
270                </xs:simpleContent>
271            </xs:complexType>
272        </xs:element>
273    </xsl:template>
274
275
276    <!-- Simple case: no attributes and no value scheme, 1-to-1 transform to an xs:element, just rename element and attributes -->
277    <xsl:template match="CMD_Element" priority="1">
278        <xsl:element name="xs:element">
279            <xsl:apply-templates
280                select="@*[name() != 'Documentation' and name() != 'DisplayPriority'] | node()"/>
281            <!-- process all Documentation and DisplayPriority attributes -->
282            <xsl:call-template name="annotations"/>
283        </xsl:element>
284    </xsl:template>
285
286    <!-- end of CMD_Element templates -->
287
288    <!-- second pass, now link to the earlier created complextype definition -->
289    <xsl:template match="ValueScheme">
290        <xsl:variable name="uniquePath">
291            <xsl:call-template name="printComponentId">
292                <!-- start from the CMD_Element above and go upwards in the tree -->
293                <xsl:with-param name="node" select=".."/>
294            </xsl:call-template>
295        </xsl:variable>
296
297        <xsl:attribute name="type">
298            <xsl:text>cmd:complextype</xsl:text>
299            <xsl:value-of select="$uniquePath"/>
300        </xsl:attribute>
301    </xsl:template>
302
303    <!-- Convert the AttributeList into real XSD attributes -->
304    <xsl:template match="AttributeList/Attribute">
305        <xs:attribute name="{./Name}">
306
307            <!-- Add a dcr:datcat if a ConceptLink element is found -->
308            <xsl:if test="normalize-space(./ConceptLink)!=''">
309                <xsl:attribute name="dcr:datcat">
310                    <xsl:value-of select="./ConceptLink" />
311                </xsl:attribute>
312            </xsl:if>
313
314            <!-- add some extra stuff if we have a CV attribute -->
315            <xsl:choose>
316
317                <!-- complex situation: CV or regex -->
318                <xsl:when test="./ValueScheme">
319                    <xs:simpleType>
320                        <xs:restriction base="xs:string">
321                            <!-- now use general rules for enumeration or pattern -->
322                            <xsl:apply-templates select="./ValueScheme/*"/>
323                        </xs:restriction>
324                    </xs:simpleType>
325                </xsl:when>
326
327                <!-- simple situation: just a basic type -->
328                <xsl:otherwise>
329                    <xsl:attribute name="type">
330                        <xsl:value-of select="concat('xs:',./Type)"/>
331                    </xsl:attribute>
332                </xsl:otherwise>
333
334            </xsl:choose>
335
336        </xs:attribute>
337    </xsl:template>
338   
339   
340    <!-- Convert patterns -->
341    <xsl:template match="pattern">
342        <xs:pattern value="{self::node()}"/>
343    </xsl:template>
344
345    <!-- Convert enumerations -->
346    <xsl:template match="enumeration">
347
348        <xsl:for-each select="item">
349            <xs:enumeration value="{node()}">
350                <!-- Add a dcr:datcat if a ConceptLink attribute is found -->
351                <xsl:apply-templates select="./@ConceptLink"/>
352                <xsl:apply-templates select="./@AppInfo"/>
353            </xs:enumeration>
354        </xsl:for-each>
355    </xsl:template>
356
357
358    <!--  default action: keep the attributes like they are -->
359    <xsl:template match="@*|node()">
360        <xsl:copy/>
361    </xsl:template>
362
363
364    <!-- except for those attributes we want to be renamed -->
365    <xsl:template match="@CardinalityMin">
366        <xsl:attribute name="minOccurs">
367            <xsl:value-of select="."/>
368        </xsl:attribute>
369    </xsl:template>
370
371    <xsl:template match="@CardinalityMax">
372        <xsl:attribute name="maxOccurs">
373            <xsl:value-of select="."/>
374        </xsl:attribute>
375    </xsl:template>
376
377    <!-- start multilinguality part -->
378
379    <!-- if the multilingual attribute is there and the field has the type string, allow multuple occurrences -->
380    <xsl:template match="@Multilingual[../@ValueScheme='string'][. = 'true'] ">
381        <!-- temporarily disabled until Arbil can deal with the <xs:import> to cope with xml:lang -->
382        <xsl:attribute name="maxOccurs">
383            <xsl:value-of>unbounded</xsl:value-of>
384        </xsl:attribute>
385    </xsl:template>
386
387    <xsl:template match="@Multilingual">
388        <!-- do nothing - only influences maxOccurs if it is true and if it is a a string element -->
389    </xsl:template>
390
391    <xsl:template match="@CardinalityMax[../@Multilingual='true'][../@ValueScheme='string']">
392        <!-- do nothing - maxOccurs should be set by Multilingual rule for strings -->
393    </xsl:template>
394
395    <!-- end multilinguality part -->
396
397    <xsl:template match="@ConceptLink">
398        <xsl:attribute name="dcr:datcat">
399            <xsl:value-of select="."/>
400        </xsl:attribute>
401    </xsl:template>
402
403    <xsl:template match="@AppInfo">
404        <xsl:attribute name="ann:label"><xsl:value-of select="."/></xsl:attribute>
405    </xsl:template>
406
407    <xsl:template match="@ValueScheme">
408        <xsl:attribute name="type">
409            <xsl:value-of select="concat('xs:',.)"/>
410        </xsl:attribute>
411    </xsl:template>
412
413    <xsl:template match="@Documentation">
414        <xsl:attribute name="ann:documentation">
415            <xsl:value-of select="."/>
416        </xsl:attribute>
417        <!--<xs:documentation><xsl:value-of select="."/></xs:documentation>-->
418    </xsl:template>
419
420    <xsl:template match="@DisplayPriority">
421        <xsl:attribute name="ann:displaypriority">
422            <xsl:value-of select="."/>
423        </xsl:attribute>
424        <!--<xs:appinfo><DisplayPriority><xsl:value-of select="."/></DisplayPriority></xs:appinfo>-->
425    </xsl:template>
426
427    <xsl:template name="annotations">
428        <xsl:if test="@Documentation or @DisplayPriority">
429            <!--<xs:annotation>-->
430            <xsl:apply-templates select="@Documentation"/>
431            <xsl:apply-templates select="@DisplayPriority"/>
432            <!--</xs:annotation>-->
433        </xsl:if>
434    </xsl:template>
435   
436</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.