W3C

[Editorial Draft] Extending and Versioning XML Languages Part 1

Draft TAG Finding 24 November 2004

This version:
http://www.w3.org/2001/tag/doc/versioning-20041124
Latest version:
http://www.w3.org/2001/tag/doc/versioning.html
Previous version:
http://www.w3.org/2001/tag/doc/versioning-20031003
Editors:
David Orchard, BEA Systems, Inc. <David.Orchard@BEA.com>
Norman Walsh, Sun Microsystems, Inc. <Norman.Walsh@Sun.COM>

Abstract

@@rewrite

This document includes some (but not yet quite all) of the material from the previous finding. It includes significant changes based upon David Orchard's updated extensibility and versioning XML writings at XML.com. A separate document contains schema language specific discussion.

Status of this Document

This document has been developed for discussion by the W3C Technical Architecture Group. It does not yet represent the consensus opinion of the TAG.

Publication of this finding does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time.

Additional TAG findings, both approved and in draft state, may also be available. The TAG expects to incorporate this and other findings into a Web Architecture Document that will be published according to the process of the W3C Recommendation Track.

Please send comments on this finding to the publicly archived TAG mailing list www-tag@w3.org (archive).

Table of Contents

1 Introduction
    1.1 Terminology
    1.2 Why Worry About Extensibility and Versioning?
    1.3 Why Extend languages?
    1.4 Why Do Languages Change?
    1.5 How Do Languages Change?
    1.6 Kinds of Languages
2 Language Questions
    2.1 Can 3rd parties extend the language?
    2.2 Can 3rd parties extend the language in a compatible way?
    2.3 Can 3rd parties extend the language in an incompatible way?
    2.4 Can the designer extend the language in a compatible way?
    2.5 Is the vocabulary a stand-alone language or an extension of another vocabulary?
    2.6 What Schema language(s)?
    2.7 Should extensions or versions be expressible in the Schema language?
3 Language Decisions
    3.1 Schema language design choices or constraints.
    3.2 Substitution Mechanism.
    3.3 Component identification
    3.4 Identification of incompatible extensions
4 Identifying and Extending Languages
5 Example
6 Understanding Extensions
7 Versioning
    7.1 Versioning Strategies
    7.2 Why Have a Strategy?
8 Version Identification Strategies
    8.1 Version Strategy: all components in new namespace(s) for each version (#1)
    8.2 Version Strategy: all new components in new namespace(s) for each compatible version (#2)
    8.3 Version Strategy: all new components in new or existing namespace(s) for each compatible version (#3)
    8.4 Version Strategy: all new components in existing or new namespace(s) for each version and a version identifier(#4)
9 Indicating Incompatible changes
    9.1 Type changes
10 Extension versus Versioning
11 Conclusion
12 References
13 Acknowledgements


1 Introduction

XML is designed for the creation of languages using a self-describing system of markup: elements and attributes, or components. The inevitable evolution of these languages, by adding, deleting, and changing parts, is called versioning. Making versioning work in practice is one of the most difficult problems in computing. Arguably, the Web rose dramatically in popularity because evolution and versioning were built into HTML and HTTP. Both systems provide explicit extensibility points and rules for understanding extensions that enable their decentralized extension and versioning.

This finding describes techniques to achieve more effective loose coupling between systems by providing a means for backwards- and forwards-compatible changes to occur when systems evolve. These techniques are designed to allow compatible changes with or without schema propagation. A number of questions, design patterns and rules are discussed with a focus towards enabling versioning in XML vocabularies, making use of XML Namespaces and XML Schema constructs. This includes not only general rules, but also rules for working with languages that provide an extensible container model, notably SOAP.

This Finding discusses the general problems associated with extensibility and versioning and how a particular technique, the _must ignore_ pattern of extensibility, can be applied to address some of those problems. Strangely, the _must ignore_ pattern used for HTML tags and HTTP headers that arguably played a significant role in the success of the Web, has not been widely adopted by XML practitioners.

This Finding aims to rectify that situation within the constraints of current Schema validation environments. It does not discuss, except in passing, techniques and strategies that involve fundamental changes to current schema validation systems.

1.1 Terminology

Extensibility is a property that enables evolvability of software. It is perhaps the biggest contributor to loose coupling in systems as it enables the independent and potentially compatible evolution of languages. Languages are defined to be [Definition: Extensible if instances of the language can include terms from other vocabularies.]

An XML Namespace is a convenient container for collecting terms that are intended to be used together within a language or across languages. It provides a mechanism for creating globally unique names.

A language has a vocabulary that may be drawn from one or more XML Namespaces (or none). [Definition: A vocabulary is a set of terms]. The syntactic structure of the language is constrained by the use of DTDs, XML Schema, other schema languages or narrative constraints expressed in the relevant language specification.

In general, the intended meaning of a vocabulary term is scoped by the language in which the term is found. However, there is some expectation that terms drawn from an XML Namespace have a consistent meaning across all languages in which they are used.

For our purposes, [Definition: a language is an identifiable set of vocabulary terms that has defined constraints.] For example, the elements and attributes of XHTML 1.0 or the names of built-in functions in XPath 2.0. Languages may or may not be defined by a schema in any particular schema language. By language, we just mean the set of elements and attributes, or components, used by a particular application.

[Definition: An instance is a realization of a language]. Documents are instances of a language. They must have a root element in XML.

[Definition: Content is data that is part of an instance of a language.] Content is part of a document. Content has one or more components.

[Definition: a Component is a realization of a term in a language.] XML elements and attributes are components.

In this finding, we describe interaction between applications and languages in terms of producers and consumers. [Definition: A producer creates or produces an instance for processing by another application. ][Definition: A consumer consumes an instance that it obtained from a producer.]

These terms and their relationships are shown below

UML diagram of language terms

In the examples mentioned above, the stylesheet processor is a consumer of the XML document that it is processing (the producer isn't mentioned); in the Web services context the roles of producer and consumer alternate as messages are passed back and forth.

Note that most Web service specifications provide definitions of inputs and outputs. By our definitions of compatibility, a Web service that updates its output schema is considered a new producer. A service that updates its input schema is a new consumer.

Versioning is an issue that effects almost all XML applications eventually. Whether it's a processor styling documents in batch to produce PDF files or Web services engaged in financial transactions, applications may receive versions of a language that they aren't expecting.

As languages evolve, it becomes possible to speak of both backwards and forwards compatability. We base our definitions of backwards and forwards compatibility on the [FOLDOC] definitions. There are two aspects of compatibility that are called out: software compatibility and schema compatibility. While it is often the case that they are directly related, sometimes they are not.

[Definition: A language change is backwards compatible if newer processors can process all instances of the old language. ] Backwards compatibility means that a newer version of a consumer can be rolled out in a way that does not break existing producers. A producer can send an older version of a message to a consumer that understands the new version and still have the message successfully processed. A software example is a word processor at version 5 being able to read and process version 4 documents. A schema example is a schema at version 5 being able to validate version 4 documents. In the case of Web services, this means that new Web services consumers, ones designed for the new version, will be able to process all instances of the old language. This means that a producer can send an old version of a message to a consumer that understands the new version and still have the message successfully processed.

[Definition: A language change is forwards compatible if older processors can process all instances of the newer language.] Forwards compatibility means that a newer version of a producer can be rolled out in a way that does not break existing consumers. Of course the older consumer will not implement any new behavior, but a producer can send a newer version of an instance and still have the instance successfully processed. An example is a word processing software at version 4 being able to read and process version 5 documents. A schema example is a schema at version 4 being able to validate version 5 documents. In the case of Web services, this means that existing Web service consumers, designed for a previous version of the language, will be able to process all instances of the new language. This means that a producer can send a newer version of a message to an existing consumer and still have the message successfully processed.

In general, backwards compatibility means that existing documents can be used by updated consumers, and forwards compatibility means that newer documents can be used by existing consumers. Another way of thinking of this is in terms of message exchanges. Backwards compatibility is where the consumer is updated and forwards compatibility is where the producer is updated, as shown below:

In broad terms, backwards compatibility means that newer producers can continue to use existing services, and forwards compatibility means that existing producers can use newer services

Compatibility is defined for the producer and consumer of an individual document instance. However, most Web service specifications provide definitions of inputs and outputs. Using these definitions of compatibility, a Web service that updates its output message schema is considered a newer producer. If a Web service updates the schema of the output message, then it is sending a newer version of the message, hence it is considered a newer producer. Conversely, updating the input message schema makes the service a newer consumer.

The cost of changes that are not backward or forward compatible is often very high. All the software that uses the language must be updated to the newer version. The magnitude of that cost is directly related to whether the system in question is open or closed.

[Definition: A closed system is one in which all of the producers and consumers are more-or-less tightly connected and under the control of a single organization.] Closed systems can often provide integrity constraints across the entire system. A traditional database is a good example of a closed system: all of the database schemas are known at once, all of the tables are known to conform to the appropriate schema, and all of the elements in the each row are known to be valid for the schema to which the table conforms.

From a versioning perspective, it might be practical in a closed system to say that a new version of a particular language is being introduced into the system at such and such a time and all of the data that conforms to the previous version of the schema will be migrated to the new schema.

[Definition: An open system is one in which some producers and consumers are loosely connected or are not controlled by the same organization. The internet is a good example of an open system.]

In an open system, it's simply not practical to handle language evolution with universal, simultaneous, atomic upgrades to all of the software components. Existing producers and recievers outside the immediate control of the organization that's publishing a changed language will continue to use the previous version for some (possibly long) period of time.

Finally, it's important to remember that systems evolve over time and have different requirements at different stages in their life cycle. During development, when the first version of a language is under active development, it may be valuable to persue a much more aggressive, draconian versioning strategy. After a system is in production and there is an expectation of stability in the language, it may be necessary to proceed with more caution. Being prepared to move forward in a backwards and forwards compatible manner is the strongest argument for worrying about versioning at the very beginning of a project.

1.2 Why Worry About Extensibility and Versioning?

As documents, or messages, are exchanged between applications, they are processed. Most applications are designed to discriminate between valid and invalid inputs. In order to have any sort of interoperability, a language must be defined or described in some normative way so that the terms "invalid" and "valid" have meaning.

There are a variety of tools that might be employed for this purpose (DTDs, W3C XML Schema, RELAX NG, Schematron, etc.). These tools might be augmented with normative prose documentation or even some application-specific validation logic. In many cases, the schema language is the only validation logic that is available.

It is almost unheard of for a single version of a language to be deployed without requiring some kind of augmentation. Invariably, the original language designer did not include certain terms and constraints. In fact, good designers should not try to define all the possible terms and constraints. This is sometimes called "boiling the ocean". Knowing that a language will not be all things to all people, a language designer can allow parties to extend instances of the language or the language itself. Typically the tools will allow the language designer to specify where extensions in the instance and extensions in the language are allowed. Of note, we do not call extending an instances of a language a new version. This scopes our discussion of versioning to changes in a language, not changes to instaces.

Whether you've deployed ten services, or a hundred, or a million, if you change a language in such a way that all those services will consider instances of the new language invalid, you've introduced a versioning problem with real costs.

Once a language is used outside of its development environment, there will be some cost associated with changing it: software, user expectations, and documentation may have to be updated to accomodate the change. Once a language is used in environments outside of a single realm of control, any changes made will introduce multiple versions of the language.

1.5 How Do Languages Change?

At the most basic level, languages can change in only a few ways:

Of course, the difference between two versions of a language can be an arbitrary number of these changes.

One of the most important aspects of a change is whether or not it is backwards or forwards compatible.

Some typical backwards- and forwards-compatible changes:

Some typical forwards-compatible changes:

Some typical backwards-compatible changes:

Some typical incompatible changes:

1.6 Kinds of Languages

Ultimately, there are different kinds of languages. The versioning approaches and strategies that are appropriate for one kind of language may not be appropriate for another. Among the various kinds of vocabulares, we find:

This is by no means an exhaustive list. Nor are these categories completely clear cut. MathML can certainly be used standalone, for example, and languages like SVG are a combination of standalone, containers, and mixtures.

2 Language Questions

Given the definitions of compatibility described above, what questions must the language designer consider?

3 Language Decisions

Upon answering these questions, there are some key decisions that a language developer makes, whether they are consciously made or not.

4 Identifying and Extending Languages

Designing extensibility into languages typically results in systems that are more loosely coupled. Extensibility allows authors to change instances without going through a centralized authority, and may allow the centralized authority greater opportunities for versioning. The common characteristic of a compatible change is the use of extensibility.

A supreme example of the benefits of extensibility is HTML. The first version of HTML was designed for extensibility; it said that _unknown markup_ may be encountered. An example of this in action is the addition of the IMG tag by the Mosaic browser team.

The first rule introduced in this Finding relating to extensibility is:

Good Practice

Allow Extensibility rule: Languages SHOULD be designed for extensibility.

A fundamental requirement for extensibility is to be able to determine the language of elements and attributes. XML Namespaces [13] provide a mechanism for associating a URI with an XML element or attribute name, thus specifying the language of the name. This also serves to prevent name collisions.

HTML did not have the ability to distinguish between the languages of extensions. This meant that authors could produce the same element name but with different interpretations, and software would have no way of determining which interpretation was applicable. This is a great part of the motivation to move from HTML to the XML vocabulary of HTML, XHTML.

W3C XML Schema [14] provides a mechanism called a wildcard, <xs:any>, for controlling where elements from certain namespaces are allowed. The wildcard indicates that elements in specified namespaces are allowed in instance documents where the wildcard occurs. This allows extension in a well-defined manner. A consumer of extended documents can identify and, depending upon its processing model, safely ignore the extensions it doesn't understand.

<xs:any> uses the namespace attribute to control what namespaces extension elements can come from. The most interesting values for this attribute are: ##any, which means one can extend the schema using an element from any possible namespace; ##other, which only allows extension elements from namespaces other than the target namespace of the schema; and ##targetnamespace, which only allows extension elements from the target namespace of the schema.

<xs:any> uses the processContents attribute to control how a XML parser validates extended elements. Permissible methods include _lax_ - validate any elements from supported namespaces but ignore all other elements, _strict__validate all elements, and _skip__validate no elements. This Finding recommends _lax_ validation, as it is the most flexible and is the typical choice for Web services specifications.

RDF/OWL and RelaxNG are 2 other popular technologies for schema design. They have different mechanisms for allowing and controlling schema evolution.

5 Example

Suppose that you have designed a language for handling personal information consisting of a single _Name_ element. The first version of the Name contains a _first_ and a _last_ element. There are a variety of strategies for extensibility and versioning, detailed later. This example will simply show the "new components in new namespace" strategy.

The language designer and 3rd parties can now use different namespaces for their versions. The language designer makes a variety of choices, particularly the schema language, that affect their strategy for namespaces. Thus the first rule for namespaces covers all language choices, but is open to extension based upon other design choices.First the rule for namespaces:

Good Practice

Allow Extensions in Other Namespace rule: The extensibility point SHOULD at least allow for extension in other namespaces.

The rule for allowing extensibility:

Good Practice

Full Extensibility rule: All XML Elements SHOULD allow for element extensibility after element definitions, and allow any attributes.

In general, an extension can be defined by a new specification that makes a normative reference to the earlier specification and then defines the new element. No permission should be needed from the authors of the specification to make such an extension. In fact, the major design point of XML namespaces is to allow decentralized extensions. The corollary is that permission is required for extensions in the same namespace. A namespace has an owner; non-owners changing the meaning of something can be harmful.

Attribute extensions do not have non-determinism issues because the attributes are always unordered and the model group for attributes uses a different mechanism for associating attributes with schema types than the model group for elements.

6 Understanding Extensions

Ideally, producers should be able to extend existing XML documents with new elements without consumers having to change existing implementations. Extensibility is one step towards this goal, but achieving compatibility also requires a processing model for the extensions. The behavior of software when it encounters an extension should be clear. For this, we introduce the next rule:

Good Practice

Provide Processing Model Rule: Languages SHOULD specify a processing model for dealing with extensions.

Achieving forwards-compatible evolution requires that the processing model must be a substitution mechanism. The instance containing the extension, which isn't known by the consumer, must be transformed into an instance which is of a type known by the consumer.

Good Practice

Provide Substitution model: Languages MUST provide a substitution model for forwards-compatible evolution.

The simplest substitution model that enables compatible changes is to ignore content that is not understood. This rule is:

Good Practice

Must Ignore Rule: Document consumers MUST ignore any XML attributes or elements in a valid XML document that they do not recognize.

This rule does not require that the elements be physically removed; only ignored for processing purposes. There is a great deal of historic usage of the Must Ignore rule. HTML 1, 2 and 3.2 follow the Must Ignore rule as they specify that any unknown start tags or end tags are mapped to nothing during tokenization. HTTP 1.1 [7] specifies that a consumer should ignore any headers it doesn't understand: "Unrecognized header fields SHOULD be ignored by the recipient and MUST be forwarded by transparent proxies." The Must Ignore rule for XML was first standardized in the WebDAV specification RFC 2518 [6] section 14 and later separately published as the Flexible XML Processing Profile [3].

There are two broad types of Must Ignore rules for dealing with extensions, either ignoring the entire tree or just the unknown element. The rule for ignoring the entire tree is:

Good Practice

Must Ignore All Rule: The Must Ignore rule applies to unrecognized elements and their descendents in data-oriented formats.

For example, if a message is received with unrecognized elements in a SOAP header block, they must be ignored unless marked as _Must Understand_ (see Rule 10 below). Note that this rule is not broken if the unrecognized elements are written to a log file. That is, _ignored_ doesn_t mean that unrecognized extensions can_t be processed; only that they can_t be the grounds for failure to process.

Other applications may need a different rule as the application will typically want to retain the content of an unknown element, perhaps for display purposes. The rule for ignoring the element only is:

Good Practice

Must Ignore Container Rule: The Must Ignore rule applies only to unrecognized elements in presentation-oriented formats.

This retains the element descendents in the processing model so that they can still affect interpretation of the document, such as for display purposes.

Ignoring content is a simple solution to the problem of substitution. In order to achieve a compatible evolution, the newer instances of a language must be transformable (or substitutable) into older instances. Object systems typically call this _polymorphism_, where a new type can behave as the old type.

Other substitution models have been successfully deployed. One such model is a fallback model, where alternate elements are provided if the consumer does not understand the extension. XSLT 2.0 provides such a model. Another model is that a transform from the new type to the old type is made available, either by value or reference.

As desirable as compatible evolution often is, sometimes a language may not want to allow it. In this model, a consumer will generate a fault if it finds a component it doesn_t understand. An example might be a security specification where a consumer must understand each and every extension. This suffers from the significant drawback that it does not allow compatible changes to occur in the language, as any changes require both consumer and producer to change.

7 Versioning

A language designer decides how new versions of their language, as well as extensions, are related to previous versions. They decide how to use namespace names, component names for their language, as well as possibly introducing versioning-specific components such as version identifiers and incompatible extension identifiers. When a new version of a language is required, the author must make a decision about the namespace name for names in the new language.

Version identification has traditionally been done with a decimal separating the major versions from the minor versions, ie _8.1_, _1.0_. Often the definition of a _major_ change is that it is incompatible, and the definition of a _minor_ change is that it is forwards- and/or backwards - compatible. Usually the first broadly available version starts at _1.0_. A compatible version change from 1.0 might be identified as _1.1_ and an incompatible change as _2.0_. It should be noted that this is idealistic as there abundant cases where this system does not hold. New major version identifiers are often aligned with product releases, or incompatible changes identified as a _minor_ change. A good example of an incompatible changed identified as a minor change is XML 1.1. XML 1.0 processors cannot process all XML 1.1 documents because XML 1.1 extended XML 1.0 where XML 1.0 does not allow such extension.

7.1 Versioning Strategies

Versioning is a broad and complex issue. Different communities have different notions about what constitutes a version, what constitutes a reasonable policy, and what the appropriate behavior is in the face of deviations from that policy. Historically, it has always proved more complicated in practice than in theory.

In broad terms, the approaches to versioning fall into a number of classes ranging from "none" to a "big bang":

There's no single approach that's always correct. Different application domains will choose different approaches. But by the same token, the approaches that are available depend on other choices, especially with respect to namespaces. This dependency makes it imperative to plan for versioning from the start. If you don't plan for versioning from the start, when you do decide to adopt a plan for versioning, you may be constrained in the available approaches by decisions that you've already made.

A language goes through a common lifecycle of iterative development followed by deployment. These place in the lifecycle will affect the selection of the versioning strategy

Just as there are a number of approaches, there are a number of strategies for implementing an approach. The internet - including MIME, markup languages, and XML languages have succesfully used various strategies, either singly or in combination. Summaries of strategies and requirements have been produced for earlier technologies and guided XML Namespaces and Schema, such as [Web Architecture: Extensible Languages].

For any given approach, some strategies may be more appropriate than others. Among the strategies we find:

  • Must Understand. consumers must understand all of the elements and attributes received and are expected to abort processing if they do not. SOAP processors must understand headers that are explicitly identified to be mandatory.

  • Must Ignore. consumers must ignore elements or attributes that they do not understand. Sometimes the must understand and must ignore approaches can be combined for more selective use. SOAP processors must ignore headers they do not recognize unless the header explicitly identifies itself as one that must be understood.

    There are 2 variations of the Must Ignore strategy:

    • Must Ignore All This variation on must ignore requires the consumer to ignore an element or attribute it does not understand and, in the case of elements, all of the descendents of that element. Most data applications, such as Web services that use SOAP header blocks or WSDL extensions, adopt this approach to dealing with unexpected markup. For XML, the Must Ignore all rule was first standardized in the WebDAV specification RFC 2518 [WebDAV] section 14 and later separately published as the [FlexXMLP].

    • Must Ignore Container. This variation on must ignore requires the consumer to ignore an element or attribute that it does not understand, but in the case of elements, to process the children of that element. The Must Ignore Container practice was described in [HTML 2.0]

  • Explicit Fallback. A language can provide mechanisms for explicit fallback if the extension is not supported. [MIME] provides multipart/alternative for equivalent, and hence fallback, representations of content. [HTML 4.0] uses this approach in the NOFRAMES element. In XML, the XML Inclusions specification [XInclude] provides a fallback element to handle the case where the putatively included resource cannot be retreived.

  • Explicit Testing. A language can provide a mechanism for explicit testing. The XSLT Specification provides a conditional logic element and a function to test for the existence of extension functions. This allows designers of stylesheets to deal with different consumer capabilities in an explicit fashion.

Languages can choose a mixture of approaches. For example, XSLT provides both an explicit fallback mechanism for some conditions and explicit testing for others. The SOAP specification, another example, specifies Must Ignore as the default strategy and the ability to dynamically mark components as being in the Must Understand strategy.

7.2 Why Have a Strategy?

Different kinds of languages and different versioning strategies expose different problems. If you don't have a strategy at all, you are effectively choosing the "no versioning" strategy.

It's probably obvious that attempting to deploy a system that provides no versioning mechanism is frought with peril. Putting the burden of version "discovery" on consumers is probably impractical in anything except a closed system.

At the other end of the spectrum is the "big bang" approach which is also problematic.

"Big bang" is a very coarse-grained approach to versioning. It establishes a single version identifier, either a version number or namespace name, for an entire document.

The semantics of the "big bang" are that applications decide on the basis of the document version whether or not they know how to process that document. If the version isn't recognized, the entire document is rejected.. Typically, when introducing a new version using the big bang approach, all of the software that produces or consumes the instance documents is updated in a sweeping overhaul in which the entire system is brought down, the new software deployed and the system is restarted. This big bang approach to versioning is practical only in circumstances where there is a single controlling authority, and even in that case, it carries with it all manner of problems. The process can take a considerable amount of time, leaving the system out of commission for hours if not days. This can result in significant losses if the system is a key component of a revenue generating business process and the cost of coordinating the system overhaul can also be quite costly as well.

Another approach to mitigate against a complete overhaul is to run parallel versions of the system, often with proxies or gateways between them. However, this too has its costs as multiple versions of the software must be supported and maintained over time and there is the added cost of developing the proxy or gateway between the two environments.

The "big bang" approach is appropriate when the new version is radically different from its predecessor. But in many cases, the changes are incremental and often a consumer could, in practice, cope with the new version. For example, it might be that there are many messages that don't use any features of the new version or perhaps it is appropriate to simply ignore elements that are not recognized.

For example, consider two services exchanging messages. Imagine that some future version of the language that they are using defines a new "priority" element. Because producers and consumers are distributed, it may happen that an old consumer, one unprepared for a priority element, encounters a message sent by a newer producer.

If big bang versioning is used, old systems will reject the new message. However, if the versioning strategy instead allowed the old consumer to simply ignore unrecognized content, it's quite possible that other components of the system could simply adapt to the previous behavior. In effect, the old system would ignore the priority element and its descendents so it would "see" a message that looks just like the old format it is expecting.

For the producer, the result would be that the request is fulfilled, though perhaps in a more or less timely fashion than expected. In many cases this may be better behavior than receiving an error. In particular, producers using the new format can be written to cope with the possibility that they will be speaking to old consumers.

If the new system needs to make sure that priority is respected, then it can change the purchase order's name or namespace to indicate that the new behavior is not considered backwards compatible.

What is needed is some sort of middle ground solution. An evolving system should be designed with backwards and forwards compatibility in mind.

One approach is to use version numbers, with a goal of using "major version" changes for incompatible developments and "minor version" changes for compatible ones.

Unfortunately, version numbers often wind up looking very similar to the big bang approach. Each language is given a version identifier, almost always a number, that's incremented each time the language changes. Although it's possible to design a system with version numbers that enables both backward and forward compatibility, for example XSLT, typically, a version change is treated as if that the new language is not backwards compatible with the old language.

Some efforts, such as HTTP, try to have the best of both worlds by allowing for extensibility (in HTTP's case, via headers) as well as version numbers that explicitly identify when a new version is backwards compatible with an old version.

One argument in favor of version numbers is that they allow one to determine what is a 'new version' and what is an 'old version'. But in practice this is not necessarily true. For example, RSS has 0.9x, 1.x, and 2.x versions, all being actively developed in parallel. In effect the version numbers, even though they appear to be ordered, are simply opaque identifiers. Using version numbers does not gaurantee that version 1+x has any particular relationship to version 1.

The self-describing and extensible nature of XML markup, and the addition of XML Namespaces, provide a much better framework for developing languages that can evolve.

8 Version Identification Strategies

There are a large variety of version identification designs. A few of the most common are listed below and described in more detail later.

  1. all components in new namespace(s) for each version

    ie version 1 consists of namespaces a + b, version 1.1 consists of namespaces c + d; or version 1 consists of namespace a, version 1.1 consists of namespace b.

  2. all new components in new namespace(s) for each compatible version

    ie version 1 consists of namespaces a + b; version 1.1 consists of namespaces a + b + c; version 2.0 consists of namespaces d + e.

  3. all new components in existing or new namespace(s) for each compatible version

    ie version 1 consists of namespace a, version 1.1 consists of namespace a, version 2 consists of namespace b; or version 1 consists of namespace a, version 1.1 consists of namespace a + b.

  4. all new components in existing or new namespace(s) for each version and a version identifier

    ie version 1 consists of namespace a + b + version attribute _1_, version 2 consists of namespace c + d + version attribute _2_.

Whatever the design chosen, the language designer must decide the component name, namespace name, and any version identifier for new and all existing components. The trade-offs between the decisions relate to the importance of:

Elaborating on these designs is illustrative.

8.4 Version Strategy: all new components in existing or new namespace(s) for each version and a version identifier(#4)

Using a version identifier, the name instances would change to show the version of the name they use, such as:

The last example shows that the middle is now a mandatory part of the name.

A significant downside with using version identifiers is that software that supports both versions of the name must perform special processing on top of XML and namespaces. For example, many components _bind_ XML types into particular programming language types. Custom software must process the version attribute before using any of the _binding_ software. In Web services, toolkits often take SOAP body content, parse it into types and invoke methods on the types. There are rarely _hooks_ for the custom code to intercept processing between the _SOAP_ processing and the _name_ processing. Further, if version attributes are used by any 3rd party extensions_say mid:middle has a version_then the schema cannot refer to the correct middle.

9 Indicating Incompatible changes

Given adoption of the Must Ignore rule, it is often the case that the creator of an extension or a new version wants to require that the consumer understand the extension, overriding the Must Ignore rule. The previous section showed how a version author could use new namespace names, element names, or version numbers to indicate an incompatible change. An extension author does not have these mechanisms available for indicating an incompatible or mandatory extension. A language provider that wants to allow extension authors to indicate incompatible extension must provide a mechanism for indicating that consumers must understand the extension.

Good Practice

Provide Must Understand Rule: Container languages SHOULD provide a _Must Understand_ model for indicating extensions that override a default Must Ignore Rule.

This rule and the Must Ignore rule work together to provide a stable and flexible processing model for extensions.

Must Understand flag

Arguably the simplest and most flexible over-ride technique is a Must Understand flag that indicates whether the item must be understood. The SOAP [8], WSDL [9], and WS-Policy [10] attributes and values for specifying understand are respectively: soap:mustUnderstand=_1_, wsdl:required=_1_, wsp:Usage=_wsp:Required_. SOAP is probably the most common case of a container that provides a Must Understand model. The default value is 0, which is effectively the Must Ignore rule.

A language designer can re-use an existing Must Understand model by constraining their language to an existing Must Understand model. A number of Web services specifications have done this by specifying that the components are SOAP header blocks, which explicitly brings in the SOAP Must Understand model.

A language designer can design a Must Understand model into their language. A Must Understand flag allows the producer to insert extensions into the container and use the Must Understand attribute to over-ride the must Ignore rule. This allows producers to extend instances without changing the extension element_s parent_s namespace, retaining backwards compatibility. Obviously the consumer must be extended to handle new extensions, but there is now a loose coupling between the language_s processing model and the extension_s processing model. A Must Understand flag is provided below:

An example of an instance of a 3rd party indicating that a middle component is an incompatible change:

Specification of a Must Understand flag must be treated carefully as it can be computationally expensive. Typically a processor will either: perform a scan for Must Understand components to ensure it can process the entire document, or incrementally process the instance and is prepared to rollback or undo any processing if an not understood Must Understand is found.

There are other refinements related to Must Understand. One example is providing an element that indicates which extension namespaces must be understood, which avoids the scan of the instance for Must Understand flags.

It is also possible to re-use the SOAP processing model with it's mustUnderstand.

10 Extension versus Versioning

The usage of namespace names for identifying components has led to the interesting situation where the distinction between an extension and a version can be quite blurred, depending upon the language designer_s choices.

One rough way of thinking of these two concepts is that extension is typically the addition of components over space; that is, designers other than the language_s creator are adding components. Versioning is typically the addition of components over time, under the designer_s explicit control. In either case, a change to the language may be done in a compatible or an incompatible way. The simple cases of extensions are compatible decentralized additions and versions are compatible or incompatible centralized changes are how we typically distinguish the terms. But these break down depending upon how the language is designed.

There are a couple of scenarios that illustrate the ambiguity in these terms. Imagine that version 1.0 of a Name consists of _First_ and _Last_ elements. A 3rd party author extends the Name with a _middle_ element in a new namespace which they control.

In scenario 1, the Name author decides to formally incorporate the middle name as an optional (and hence compatible) addition to the name, producing version 1.1 of the Name type. They do this by referring to the third party_s definition and namespace for middle names. This is typically considered a new _version_ of the Name and would probably result in a new schema definition. If the Name author re-uses namespace names for compatible revisions, there will be no difference in an instance document containing middle that is of Version 1.0 or Version 1.1 type. The instance documents are the same, and thus the distinction between a _version_ and an _extension_ is meaningless for an individual document.

In scenario 2, the middle author decides that the middle name is a mandatory part of the Name type. They were provided a mechanism for indicating an incompatible change and they use it. Now an instance of Name with the middle is incompatible with version 1.0 of the Name. What _version_ of the Name is this middle, and is the middle an _extension_ or a _version_? It isn_t 1.0. It_s probably more accurately thought of as a version defined by the 3rd party. Again, the presence of the _extension_ is actually an incompatible change.

These two examples_a 3rd party extension being added into a compatible version and a 3rd party extension resulting in an incompatible version_show the ability to specify (in)compatibility has blurred the distinction between these two terms.  

11 Conclusion

This Finding describes a number of questions, decisions and rules for using XML, XML Namespaces and schema languages in XML language construction and extension. The main goal of the set of rules is to allow language designers to know their options for language design, and ideally make backwards- and forwards-compatible changes to their languages to achieve loose coupling between systems.

12 References

FOLDOC
Free Online Dictionary of Computing. (See http://wombat.doc.ic.ac.uk/foldoc/.)
FlexXMLP
Flexible XML Processing Profile. (See http://www.upnp.org/download/draft-goland-fxpp-01.txt.)
MIME
RFC 1521, MIME. (See http://www.ietf.org/rfc/rfc1521.txt.)
HTML 2.0
RFC 1866, HTML 2.0. (See http://www.ietf.org/rfc/rfc1866.txt.)
WebDAV XMLIgnore post
Yaron GolandXML Ignore proposed for WebDAV (See http://lists.w3.org/Archives/Public/w3c-dist-auth/1997AprJun/0190.html.)
WebDAV
RFC 2518, WebDAV (See http://www.ietf.org/rfc/rfc2518.txt.)
HTML 4.0
HTML 4.0. (See http://www.w3.org/TR/1998/REC-html40-19980424/.)
TBL Mandatory Extensions
Berners-Lee. Web Architecture: Mandatory extensions. (See http://www.w3.org/DesignIssues/Mandatory.html.)
TBL Extensible languages
Berners-Lee. Web Architecture: Extensible languages. (See http://www.w3.org/DesignIssues/Extensible.html.)
TBL Evolution
Berners-Lee. Web Architecture: Evolvability. (See http://www.w3.org/DesignIssues/Evolution.html.)
Web Architecture: Extensible Languages
Berners-Lee and Connolly, ed. Web Architecture: Extensible Languages World Wide Web Consortium, 1998. (See http://www.w3.org/TR/1998/NOTE-webarch-extlang-19980210.)
HTML Document types
Connolly, ed. HTML Document dialects World Wide Web Consortium, 1996. (See http://www.w3.org/MarkUp/WD-doctypes.)
SOAP 1.2
W3C Recommendation, SOAP 1.2 Part 1: Messaging Framework (See http://www.w3.org/TR/SOAP/.)
WSDL 1.1
W3C Note, WSDL 1.1 (See http://www.w3.org/TR/WSDL/.)
XML 1.0
W3C Recommendation, XML 1.0 (See http://www.w3.org/TR/REC-xml.)
XInclude
W3C Working Draft, XML Inclusions (See http://www.w3.org/TR-Xinclude.)
XML Namespaces
W3C Recommendation, XML Namespaces (See http://www.w3.org/TR/REC-xml-names.)
XML Schema Part 2
W3C Recommendation, XML Schema, Part 2 (See http://www.w3.org/TR/xmlschema-2.)
XML Schema Wildcard Test Collection
XML Schema Wildcard Test collection (See http://www.w3.org/XML/2001/05/xmlschema-test-collection/result-ms-wildcards.htm.)
XFront Schema Best Practices
XFront Schema Best Practices (See http://www.xfront.com/BestPracticesHomepage.html.)
XML.com Schema Design Patterns
Dare ObasanjoXML.com Schema design patterns (See http://www.xml.com/pub/a/2002/07/03/schema_design.html.)
Dave Orchard writings on Extensibility and Versioning
Dave Orchard writings on extensibility and versioning (See http://www.pacificspirit.com/Authoring/Compatibility.)

13 Acknowledgements

The author thanks the many reviewers that have contributed to the article, particularly David Bau, William Cox, Ed Dumbill, Chris Ferris, Yaron Goland, Hal Lockhart, Mark Nottingham, Jeffrey Schlimmer, Cliff Schmidt, and Norman Walsh.