4
votes

How can I convert an XSD 1.1 schema to an XSD 1.0 schema automatically by stripping out all the 1.1 features and leaving only the subset that is compatible with XSD 1.0?

I realize that this would impose restrictions on how many XSD 1.1 features you could take advantage of, but the use case I'm imagining is a schema where you publish both an XSD 1.1 version and a more compatible XSD 1.0 version, with both describing the same data structure but with the 1.1 version having a few additional <assert> data integrity checks.

2

2 Answers

2
votes

If you are imagining the publication of both a 1.1 schema and a related 1.0 schema, then probably the simplest and best way is to use the vc: namespace described in the XSD 1.1 specification. You can use the vc: namespace to mark 1.1 features like the assertions you mention (or the declarations containing them), and to supply 1.0 equivalents or near-equivalents.

We can use this to mark the xs:assert in an example from the XSD 1.1 spec as a 1.1-only feature:

<xs:complexType name="arrayType">
 <xs:sequence>
  <xs:element name="entry" minOccurs="0" maxOccurs="unbounded"/>
 </xs:sequence>
 <xs:attribute name="length" type="xs:int"/>
 <xs:assert test="@length eq fn:count(./entry)"
   xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
   vc:minVersion="1.1"/>
</xs:complexType>

Any XSD 1.1 processor is required to understand the vc: namespace and filter the schema document accordingly (accepting things with vc:minVersion less than or equal to 1.1, or vc:maxVersion greater than 1.1, and so on). So the schema document with the vc:* attributes can be shipped as a 1.1 schema.

A conforming 1.0 processor could be updated to understand the vc: namespace, but I don't know of any that have been. So for use by 1.0 processors, the schema document needs to be filtered before they see it.

Like kjhughes, I think an XSLT stylesheet is probably your best bet for that filtering. But using the vc:* namespace makes it easy to do reliably and does not require that the schema author minimize the use of 1.1 features in order to simplify the transformation.

It's easy enough to write a stylesheet to perform the necessary filtering, but in fact you don't have to: There is an XSLT 1.0 stylesheet that does the job (full disclosure; I wrote it). There used to be a working online demo as well, but I see that bit rot has set in, and it doesn't seem to work in current browsers; I'll fix it when I have time. The documentation may still be useful.

1
votes

As you anticipate, no general case conversion is possible. However, given that you're in control of the v1.1 XSD, there's hope. Appendix G.1 of the XSD v1.1 Recommendation summarizes the changes compared to XSD v1.0. In short, don't rely upon any new constructs or behaviors described in Appendix G.1.

If you stay clear of all changes other than the use of xsd:assert that you mentioned, you could use a simple XSLT transformation to maintain the mapping from your v1.0 XSD to your v1.1 XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="xsd:assert"/>
</xsl:stylesheet>