More on XSD versioning

Raimond posted this comment asking a question about my approach to XSD versioning:

I see how this model can solve a bunch of the problems, but how to deal with removal of allowed elements?

Lets say we have a V1:
<Customer>
<Name>John Doe</Name>
</Customer>

In V2 it is discovered that it should actually be
<Customer>
<FirstName>John</FirstName>
<LastName>John</LastName>
</Customer>

I don't see how this case would fit with the proposed model.

He's right, the model I describe does not deal with removal of elements. I divide the versioning problem into three types of changes:

  1. Adding new constructs (types, elements, portTypes, etc.)
  2. Extending existing constructs
  3. Changing existing constructs

You can do (1) without concern. You can do (2) using the model I described. For (3), you typically need to define a new set of types in a new namespace (there might be some serializer-level trickery to avoid this, but this is the general rule). I'm okay with this breakdown for two reasons. First, I think that 1 and 2 are far more common. Second, I have a way to handle 3 using a new targetNamespace but multiplexing both the old and the new namespace to a single object model. That would deal with the removal problem. I'll post code to do that too.

There is another way around this problem too. Raimond asked about the removal of “allowed” elements, not “required” elements. I'm a big fan of making all elements optional, with the common exception of a required identity element. In other words, if you're designing a schema for use by multiple services and you don't know which services will be able to provide which pieces of data, you're better of designing a very loose schema that focuses on describing the shape of the data if it's present.

If the <name> element were optional (allowed but not required) in Raimond's example, then not using it in V2 is not a problem. In other words, you could move from this V1 definition:

<complexType name=”CustomerType”>
  <sequence>
    <element name=”Name” type=”string” minOccurs=”0” />
  </sequence>
</complexType>

to this V2 definition:

<complexType name=”CustomerType”>
  <sequence>
    <element name=”Name” type=”string” minOccurs=”0” />
    <element name=”FirstName” type=”string” minOccurs=”0” />
    <element name=”LastName” type=”string” minOccurs=”0” />
  </sequence>
</complexType>

For this to work, you have to define the rules for which elements take precedence and which are ignored if both are present. Yes, I might go that far to avoid a sweeping schema change.


Posted Apr 19 2006, 02:25 PM by tim-ewald

Comments

Steve Maine wrote re: More on XSD versioning
on 04-19-2006 2:13 PM
If you make a fundamental assumption that all structures are open content models and follow the "must ignore unknown" rule, I think this problem goes away.

In the case above, sending the V1 schema to the V2 client would result in the "Name" element being sucked into the wildcard bucket.

Under this model, the schema is invalid not because they sent the "Name" element but because the required "FirstName" and "LastName" elements are missing.

I don't think I should ever be able to tell you not to send me something. I can only tell you what I expect and ignore all the things you send me that I don't understand (or choose not to).

Steve Maine wrote re: More on XSD versioning
on 04-19-2006 2:14 PM
Oops, I said "schema is invalid" when I meant to say "instance document is invalid". My bad.
DJ wrote re: More on XSD versioning
on 04-20-2006 9:28 AM
Did I miss a previous post about not using the schema to validate your data? If everything is optional, then how do I enforce what HAS to be there?
XML Nation wrote Making everything optional
on 04-20-2006 12:51 PM
Raimond Brookman wrote re: More on XSD versioning
on 04-20-2006 2:11 PM
I agree with DJ. Some of the idea behind XML Schema (I thought :-)) was to be able to validate things.
Using this model, we end up with a V26 which allows all possible combinations from the previous 26 versions (Maybe I'm exaggerating a bit :-)).
This means you basically have a piece of code that goes through a whole lot of logic to determine which version the message *probably* is.

Or, what would be better is to have a version attribute somewhere and then use that as the reference point.

Even better would be a smarter version of xsd schema in which you could link contructs to a specific version; something like:

<xsdpp:versioning model="2.0"/>
<complexType name=”CustomerType”>
<sequence>
<element name=”Name” type=”string” minOccurs=”1” xsdpp:version-ref="1.0"/>
<element name=”FirstName” type=”string” minOccurs=”1” xsdpp:version-ref="2.0"/>
<element name=”LastName” type=”string” minOccurs=”1” xsdpp:version-ref="2.0"/>
</sequence>
</complexType>

In which the versioning tag indicates that all constructs without a specific version-ref are linked to 2.0.

We could already build this kind of functionality by extending the schema validation a bit... maybe a thought for a rainy day :-)
Raimond Brookman wrote re: More on XSD versioning
on 04-20-2006 2:14 PM
Or, as I just thought, just use XSLT to create version specific schema definitions using these annotations.

(and off course we need some serializer support...)
David Orchard wrote re: More on XSD versioning
on 04-27-2006 12:34 PM
Treating the "new" structure as optional data and having redudancy is very good for compatible versioning. I wrote up this exact example of moving from a name string to a structure in a compatible way a couple years ago in http://www.pacificspirit.com/blog/2004/06/14/why_putting_extra_structure_in_v10_is_good

Dare Obasanjo aka Carnage4Life wrote Tim Ewald on Versioning XML Web Services with XSD
on 05-14-2006 4:53 PM
Ken Brubaker wrote Tim Ewald's solution for XML Schema versioning
on 11-28-2006 7:55 AM
Tim Ewald addresses the XML Schema versioning issue head on.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?