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

Last change on this file since 2311 was 2311, checked in by mwindhouwer, 12 years ago

M comp2schema-v2/comp2schema.xsl

  • disabled xml:base again, as Arbil first needs to be able to deal with it ...
  • Property svn:executable set to *
  • Property svn:keywords set to
    Date
    Rev
File size: 17.0 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2
3<!--
4    $Rev: 2311 $
5    $Date: 2012-10-16 07:30:31 +0000 (Tue, 16 Oct 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                <!-- DISABLED (Arbil needs to handle it first) allow @xml:base as a residue of XInclude processing -X->
221                <xs:attribute ref="xml:base"/>
222                -->
223                <!-- @ref to the resource proxy (TODO: put this in the CMD namespace, i.e., @cmd:ref -->                 
224                <xs:attribute name="ref" type="xs:IDREFS"/>
225                <xsl:apply-templates select="./AttributeList/Attribute"/>
226                <xsl:if test="@ComponentId">
227                    <xs:attribute name="ComponentId" type="xs:anyURI" fixed="{@ComponentId}"/>
228                </xsl:if>
229            </xs:complexType>
230
231        </xs:element>
232
233    </xsl:template>
234
235    <!-- Process all CMD_Elements, its attributes and children -->
236
237    <!-- Highest complexity: both attributes and a valuescheme, link to the type we created during the preprocessing of the ValueScheme -->
238    <xsl:template match="CMD_Element[./AttributeList][./ValueScheme]" priority="3">
239        <xs:element name="{@name}">
240
241            <!-- process all Documentation and DisplayPriority attributes -->
242            <xsl:call-template name="annotations"/>
243
244            <xsl:apply-templates select="@ConceptLink"/>
245            <xsl:apply-templates select="@CardinalityMin"/>
246            <xsl:apply-templates select="@CardinalityMax"/>
247            <xsl:apply-templates select="ValueScheme"/>
248
249        </xs:element>
250    </xsl:template>
251
252    <!-- Medium complexity: attributes (or Multilingual field) but no valuescheme, can be arranged inline -->
253    <xsl:template match="CMD_Element[./AttributeList or ./@Multilingual]" priority="2">
254        <xs:element name="{@name}">
255
256            <xsl:apply-templates select="@Multilingual"/>
257            <xsl:apply-templates select="@ConceptLink"/>
258            <xsl:apply-templates select="@CardinalityMin"/>
259            <xsl:apply-templates select="@CardinalityMax"/>
260
261            <!-- process all Documentation and DisplayPriority attributes -->
262            <xsl:call-template name="annotations"/>
263
264            <!-- <xsl:apply-templates select= "and(not(@type) and @*)"/> -->
265            <xs:complexType>
266                <xs:simpleContent>
267                    <xs:extension base="{concat('xs:',@ValueScheme)}">
268                        <xsl:apply-templates select="./AttributeList/Attribute"/>
269                        <!-- temporarily disabled -->
270                        <xsl:if test="./@Multilingual='true'">
271                            <xs:attribute ref="xml:lang" />
272                        </xsl:if>
273                    </xs:extension>
274                </xs:simpleContent>
275            </xs:complexType>
276        </xs:element>
277    </xsl:template>
278
279
280    <!-- Simple case: no attributes and no value scheme, 1-to-1 transform to an xs:element, just rename element and attributes -->
281    <xsl:template match="CMD_Element" priority="1">
282        <xsl:element name="xs:element">
283            <xsl:apply-templates
284                select="@*[name() != 'Documentation' and name() != 'DisplayPriority'] | node()"/>
285            <!-- process all Documentation and DisplayPriority attributes -->
286            <xsl:call-template name="annotations"/>
287        </xsl:element>
288    </xsl:template>
289
290    <!-- end of CMD_Element templates -->
291
292    <!-- second pass, now link to the earlier created complextype definition -->
293    <xsl:template match="ValueScheme">
294        <xsl:variable name="uniquePath">
295            <xsl:call-template name="printComponentId">
296                <!-- start from the CMD_Element above and go upwards in the tree -->
297                <xsl:with-param name="node" select=".."/>
298            </xsl:call-template>
299        </xsl:variable>
300
301        <xsl:attribute name="type">
302            <xsl:text>cmd:complextype</xsl:text>
303            <xsl:value-of select="$uniquePath"/>
304        </xsl:attribute>
305    </xsl:template>
306
307    <!-- Convert the AttributeList into real XSD attributes -->
308    <xsl:template match="AttributeList/Attribute">
309        <xs:attribute name="{./Name}">
310
311            <!-- Add a dcr:datcat if a ConceptLink element is found -->
312            <xsl:if test="normalize-space(./ConceptLink)!=''">
313                <xsl:attribute name="dcr:datcat">
314                    <xsl:value-of select="./ConceptLink" />
315                </xsl:attribute>
316            </xsl:if>
317           
318            <!-- add some extra stuff if we have a CV attribute -->
319            <xsl:choose>
320
321                <!-- complex situation: CV or regex -->
322                <xsl:when test="./ValueScheme">
323                    <xs:simpleType>
324                        <xs:restriction base="xs:string">
325                            <!-- now use general rules for enumeration or pattern -->
326                            <xsl:apply-templates select="./ValueScheme/*"/>
327                        </xs:restriction>
328                    </xs:simpleType>
329                </xsl:when>
330
331                <!-- simple situation: just a basic type -->
332                <xsl:otherwise>
333                    <xsl:attribute name="type">
334                        <xsl:value-of select="concat('xs:',./Type)"/>
335                    </xsl:attribute>
336                </xsl:otherwise>
337
338            </xsl:choose>
339
340        </xs:attribute>
341    </xsl:template>
342   
343   
344    <!-- Convert patterns -->
345    <xsl:template match="pattern">
346        <xs:pattern value="{self::node()}"/>
347    </xsl:template>
348
349    <!-- Convert enumerations -->
350    <xsl:template match="enumeration">
351
352        <xsl:for-each select="item">
353            <xs:enumeration value="{node()}">
354                <!-- Add a dcr:datcat if a ConceptLink attribute is found -->
355                <xsl:apply-templates select="./@ConceptLink"/>
356                <xsl:apply-templates select="./@AppInfo"/>
357            </xs:enumeration>
358        </xsl:for-each>
359    </xsl:template>
360
361
362    <!--  default action: keep the attributes like they are -->
363    <xsl:template match="@*|node()">
364        <xsl:copy/>
365    </xsl:template>
366
367
368    <!-- except for those attributes we want to be renamed -->
369    <xsl:template match="@CardinalityMin">
370        <xsl:attribute name="minOccurs">
371            <xsl:value-of select="."/>
372        </xsl:attribute>
373    </xsl:template>
374
375    <xsl:template match="@CardinalityMax">
376        <xsl:attribute name="maxOccurs">
377            <xsl:value-of select="."/>
378        </xsl:attribute>
379    </xsl:template>
380
381    <!-- start multilinguality part -->
382
383    <!-- if the multilingual attribute is there and the field has the type string, allow multuple occurrences -->
384    <xsl:template match="@Multilingual[../@ValueScheme='string'][. = 'true'] ">
385        <!-- temporarily disabled until Arbil can deal with the <xs:import> to cope with xml:lang -->
386        <xsl:attribute name="maxOccurs">
387            <xsl:value-of>unbounded</xsl:value-of>
388        </xsl:attribute>
389    </xsl:template>
390
391    <xsl:template match="@Multilingual">
392        <!-- do nothing - only influences maxOccurs if it is true and if it is a a string element -->
393    </xsl:template>
394
395    <xsl:template match="@CardinalityMax[../@Multilingual='true'][../@ValueScheme='string']">
396        <!-- do nothing - maxOccurs should be set by Multilingual rule for strings -->
397    </xsl:template>
398
399    <!-- end multilinguality part -->
400
401    <xsl:template match="@ConceptLink">
402        <xsl:attribute name="dcr:datcat">
403            <xsl:value-of select="."/>
404        </xsl:attribute>
405    </xsl:template>
406
407    <xsl:template match="@AppInfo">
408        <xsl:attribute name="ann:label"><xsl:value-of select="."/></xsl:attribute>
409    </xsl:template>
410
411    <xsl:template match="@ValueScheme">
412        <xsl:attribute name="type">
413            <xsl:value-of select="concat('xs:',.)"/>
414        </xsl:attribute>
415    </xsl:template>
416
417    <xsl:template match="@Documentation">
418        <xsl:attribute name="ann:documentation">
419            <xsl:value-of select="."/>
420        </xsl:attribute>
421        <!--<xs:documentation><xsl:value-of select="."/></xs:documentation>-->
422    </xsl:template>
423
424    <xsl:template match="@DisplayPriority">
425        <xsl:attribute name="ann:displaypriority">
426            <xsl:value-of select="."/>
427        </xsl:attribute>
428        <!--<xs:appinfo><DisplayPriority><xsl:value-of select="."/></DisplayPriority></xs:appinfo>-->
429    </xsl:template>
430
431    <xsl:template name="annotations">
432        <xsl:if test="@Documentation or @DisplayPriority">
433            <!--<xs:annotation>-->
434            <xsl:apply-templates select="@Documentation"/>
435            <xsl:apply-templates select="@DisplayPriority"/>
436            <!--</xs:annotation>-->
437        </xsl:if>
438    </xsl:template>
439   
440</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.