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

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

M comp2schema-v2/comp2schema.xsl

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