Search code examples
c#.netxmlxsd.exexsd-1.1

Transform XSD 1.1 schema to c# class


I have to transform an XSD 1.1 schema to an c# class. The problem is that xsd.exe does not support XSD 1.1, in fact if I try to create an c# class from that schema I get this error:

Notice validation scheme: Element 'http://www.w3.org/2001/XMLSchema:assert' not supported in this context.

How can I get around this?


Solution

  • There is no easy way around this.

    Customizing xsd.exe behavior is generally possible, even easy. It is just a thin layer atop .NET libraries (System.Xml). But those libraries do not understand XSD 1.1, so you would have to have an XSD 1.0 document to feed them. And if you can convert your schemas into the older specification language, then you can use the unmodified xsd.exe as well.

    Could you transform an XSD 1.1 schema into an XSD 1.0 schema, for your purpose? In some instances, it might be easy. For example, a very simple XSLT transform can filter out asserts, replace the new datatypes by suitable XSD 1.0 datatypes and the like. However, the general case is somewhere between hard and unsolvable. Let's see where XSD 1.1 adds features that you can't just ignore:

    <complexType name="base">
      <complexContent>
        <sequence>
          <element ref="tns:a" minOccurs="0" maxOccurs="1"/>
          <choice minOccurs="0" maxOccurs="unbounded">
            <element ref="tns:b"/>
            <element ref="tns:c"/>
          </choice>
        </sequence>
       </complexContent>
     </complexType>
    
    <complexType name="derived">
      <complexContent>
        <restriction base="tns:base">
          <sequence>
            <choice minOccurs="0" maxOccurs="unbounded">
              <element ref="tns:b"/>
              <element ref="tns:c"/>
            </choice>
          </sequence>
        </restriction>
       </complexContent>
     </complexType>
    

    (Sample taken from here. That's a great starting point for estimating whether your particular schemas could be expressed in, or converted to, XSD 1.0.)

    The sample shows a pretty natural use of inheritance in XSD 1.1. All that the derived type really does is banning the member tns:a. To do the same thing in XSD 1.0, the type would need to list tns:a with maxOccurs='0', and the corresponding C# class will contain the a member, whether you want it or not. Such a downgrade transformation (from XSD 1.1 to XSD 1.0) is still relatively easy to put together to serve this simple example but basically impossible when you need to map particles across a whole inheritance hierarchy with such restricted optional members and/or wildcards. XSD 1.0 just isn't expressive enough.

    Now to the general question. Suppose that your schemas are unknown in advance and/or making heavy use of new XSD 1.1 features. You won't be able to convert them to XSD 1.0 and so the .NET base class library won't help you generate C# classes from them. You have two or three options left:

    • You can create the deserialization classes manually. You won't be able to validate and deserialize, but you will be able to deserialize a valid document, including enforcing proper attribute defaults (a typical side effect of validation that you will want to keep).
    • You can create your own XSD 1.1 parsing support. A very big project, although you can ignore a lot of the schema (such as the whole XSLT 2.0 spec for asserts) and still be able to end up with somewhat natural C# classes.
    • You can take an existing third party library with this feature. An empty set to choose from at the moment, I suspect. Saxon's API does not generate deserialization classes from the schema. And I'm not aware of any other XSD 1.1 implementations available on the .NET platform.