Hi Jeni,
Thanks a lot for the very detailed and instructive reply.
I had thought about changing the namespace for the XSLT 2.0
stylesheets and decided to rely on this approach as a last resort.
And you are right -- RNG is much more elegant and useful.
Thanks for finding time to reply even during the weekend.
Dimitre.
Right: using a schema to *validate* XSLT stylesheets isn't worthwhile
(and that's what the subject line indicated you were asking about),
but using a schema for other reasons (such as intellisense, or when
querying/generating XSLT using XSLT 2.0) could be, potentially.
The usual way to get around the lack of support for co-occurrence
constraints in WXS is to use xsi:type. So... you could design a schema
in which there were version 1.0 and version 2.0 types for each
element. Then use the xsi:type attribute to indicate the version
you're using in the stylesheet. For example:
<xs:element name="stylesheet" type="stylesheet" />
<!-- general type allows anything allowed by XSLT (incorporating
forwards-compatibility) -->
<xs:complexType name="stylesheet">
<xs:sequence>
<xs:element name="import" type="import"
minOccurs="0" maxOccurs="unbounded" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:any namespace="##targetNamespace" processContents="lax" />
<xs:any namespace="##other" processContents="lax" />
</xs:choice>
</xs:sequence>
<xs:attribute name="version" use="required" type="xs:decimal" />
...
</xs:complexType>
<!-- restricted type only allows XSLT 1.0 stylesheets -->
<xs:complexType name="stylesheet-v1.0">
<xs:complexContent>
<xs:restriction base="stylesheet">
<xs:sequence>
<xs:element name="import" type="import-v1.0"
minOccurs="0" maxOccurs="unbounded" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="template" type="template-v1.0" />
...
<xs:any namespace="##other" />
</xs:choice>
</xs:sequence>
<xs:attribute name="version" fixed="1.0" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<!-- restricted type only allows XSLT 2.0 stylesheets -->
<xs:complexType name="stylesheet-v2.0">
<xs:complexContent>
<xs:restriction base="stylesheet">
<xs:sequence>
<xs:element name="import" type="import-v2.0"
minOccurs="0" maxOccurs="unbounded" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="template" type="template-v2.0" />
...
<xs:any namespace="##other" />
</xs:choice>
</xs:sequence>
<xs:attribute name="version" fixed="2.0" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
and then use:
<xsl:stylesheet version="1.0" xsi:type="stylesheet-v1.0" ...>
in your stylesheet.
The trouble with this approach (aside from its complexity) is that
once you use a literal result element in your stylesheet, its content
can't be constrained based on the version of XSLT you're using. You
could declare all the literal result elements that you use in your
stylesheet, or you could use <xsl:element> and <xsl:attribute>
instead.
Other possibilities are just using an XSLT 2.0 schema all the time,
and relying on your knowledge of XSLT 1.0 to prevent you using XSLT
2.0 elements in an XSLT 1.0 stylesheet; or you could use a fake
namespace for your XSLT 2.0 stylesheets (changing it on load and on
save) and get different schemas for different stylesheets. If the
software picks up on the xsi:schemaLocation attribute, then you could
use that to indicate the schema that you wanted to use with a
particular stylesheet.
If the software supports RELAX NG, you're in better luck, because you
can use co-occurrence constraints with RNG, and wildcards in RNG are a
lot more flexible than those in WXS.
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/