Copyright © 2006 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This document is a guide to versioning XML languages using XML Schema 1.1. It shows many of the new Schema 1.1 mechanisms, provides context above the schema 1.1 WD, and solicits reader input.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document is the First Public Working Draft, published 28 September 2006, of a document which when complete is expected to become a W3C Working Group Note. It has been developed by the W3C XML Schema Working Group, as part of the W3C XML Activity, to illustrate the use of XML Schema 1.1 in defining XML languages. XML Schema 1.1 introduces a number of new features intended to make it easier to define XML languages which are flexible enough to tolerate later revision in a forward-compatible way. The current draft is not complete, but it illustrates several techniques important for the versioning of XML languages defined using XML Schema 1.1. It will be updated to make it more complete and to reflect further technical changes in the development of XML Schema 1.1. The Working Group has consensus that this draft should be published, but does not necessarily have consensus on every aspect of the exposition.
Please send comments on this document to the archived versioning mailing list public-xml-versioning@w3.org (archive).
The English version of this specification is the only officially maintained version. Information about translations of this document is available at http://www.w3.org/2003/03/Translations/byTechnology?technology=xmlschema.
Publication as a Working Draft 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. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. The group does not expect this document to become a W3C Recommendation. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document, Versioning Guide to XML Schema 1.1, is intended to provide an easily approachable description of the versioning features in the XML Schema definition language, and should be used alongside the formal descriptions of the language contained in Parts 1 and 2 of the XML Schema specification. The intended audience of this document includes application developers whose programs read and write schema documents, and schema authors who need to know about the features of the language, especially features that provide functionality above and beyond what is provided by DTDs. The text assumes that you have a basic understanding of XML, Namespaces in XML, and XML Schema.
The guide is a non-normative document, which means that it does not provide a definitive (from the W3C's point of view) specification of the XML Schema language. The examples and other explanatory material in this document are provided to help you understand XML Schema, but they may not always provide definitive answers. In such cases, you will need to refer to the XML Schema specification. To help you do this, we provide many links pointing to the relevant parts of the specification.
The W3C TAG is working on a versioning finding that provides a language-independent rationale and description of languages, extensibility, versioning, and compatibility. It is suggested reading for these topics.
As suggested in the TAG finding, creating and using multiple versions of a language is common and useful. As described, extensibility is a key contributor to versioning. It can enable forwards and backwards compatible versioning. The majority of this guide focuses on Schema 1.1 extensibility techniques that enable forwards-compatible versioning. In schema terms, this is when a schema processor with an older schema can process and validate an instance that is valid against a newer schema.
This guide focuses on describing the different ways extra content can be added to create new versions of a schema. These different ways reflects different conditions faced by schema authors. These conditions may manifest themselves as technical constraints (e.g. location of extension points where content can be added) or non-technical constraints (e.g. ownership over a schema).
XML Schema 1.1 contains a number of new extensibility mechanisms. The ones described in August 31 2006 draft are:
Weak wildcards - permits wildcards adjacent to optional elements
Updated All Group - wildcards within All Group
Negative wildcard - exclude specific namespaces and names
The mechanisms that are possible/probable/under discussion for the next draft are:
Fallback To Declared Type - use declared type if xsi:type is unknown
Auto-insertion of wildcards
Not in Schema wildcard - a wildcard that allows anything not defined in the current schema
This document does not discuss the Post Schema Validation Infoset properties as that would result in a signifcantly less readable document.
Let us start quickly by considering a name instance. It describes a name:
<name xmlns="http://www.example.org/name/1"> <given>Dave</given> <family>Orchard</family> </name>
As mentioned earlier, extensibility in the type is desired. Schema wildcards are a significant mechanism for allowing extensibility. Using XML Schema 1.1, the name owner might like to write a schema such as:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="given" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
One possible extension is adding a middle. It describes a name:
<name xmlns="http://www.example.org/name/1"> <given>Dave</given> <middle>Bryce</middle> <family>Orchard</family> </name>
The next version of the schema with middle name added might look like:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="given" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="middle" type="xs:string" minOccurs="0"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
This schema is illegal in Schema 1.0 and remains illegal in Schema 1.1 because there is a UPA (Unique Particle Attribution) rule violation with the additional optional middle and wildcard. However, Schema 1.1 has partially reduced the UPA constraints such that the following is now legal, and it will valid the previous 2 instances:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="given" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:sequence minOccurs="0"> <xs:element name="middle" type="xs:string" /> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
Alternatively, each of the elements could be wrapped in a sequence followed by a wildcard:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:sequence> <xs:element name="given" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:sequence minOccurs="0"> <xs:element name="middle" type="xs:string" /> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:sequence> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
Another alternative is each of the elements could be a reference to a model group that is the sequence of the element followed by a wildcard:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:group name="given"> <xs:sequence> <xs:element name="given" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:group> <xs:group name="middle"> <xs:sequence> <xs:element name="middle" type="xs:string" /> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:group> <xs:group name="family"> <xs:sequence> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:group> <xs:group name="name"> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:group ref="given"/> <xs:group ref="middle" minOccurs="0"/> <xs:group ref="family"/> </xs:sequence> <xs:anyAttribute/> </xs:group> <xs:element name="name" type="name:name"/> </xs:schema>
The wildcard construct enables authors to create schemas that are both forwards and backwards-compatible. The new schema is backwards compatible because it will validate old and new instances. The exception is instances that have content that is legal in the wildcard but not in the new content. An example might be a middle name that has structure or digits. However, that scenario means that an author created a middle name instance in the name namespace according to one schema AND an author defined a new name in the same namespace according to a different schema. Arguably there is an authority over the namespace that will prevent such clashes and so in practice this exception won't happen. Alternatively, we can make a slightly different compatibility guarantee, which is the new schema is backwards compatible with validate old and new instance where new instances do not have any extensions in the defined namespaces. The old schema is forwards compatible because it will validate old and new instances - of course it sees these as current and future instances.
The new schema is created by the replacement of a repeating wildcard in the original, with an optional-wildcard, optional-element, optional-wildcard sequence, in the later schema. The new schema explicitly states the entire new content model, including everything from the original schema as well as the new explicit declaration for middle, and for that reason we call it a "Complete Respecification" of the type.
The new type declared above using wildcards could be declared as an explicit <xs:restriction/> of the original type, because every document accepted by the new type is also accepted by the old. XML Schema's type <xs:restriction/> allows alteration of wildcards anywhere in the content model, like Complete Respecification, but allows the original type to be preserved. Alternatively, XML Schema's type extension mechanism <xs:extension/> [provide ref to Recommendation] provides a different way of specifiying a modified type, in which the original content is not restated, but only the new elements are explicitly referenced. The differences are: (1) xs:extension allows new content only at the end of the model and (2) using wildcards as shown above, the original type will accept not only documents in the original language, but also documents containing the middle name, something that's not true in typical uses of xs:extension. Thus the schema author of new version of a type has 3 options outlined above: 1) Complete Respecification without explicit use of xs:restriction; 2) Complete Respecification with explicit use of xs:restriction; 3) xs:extension.
All-groups can use the updated wildcard:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:all> <xs:element name="given" type="xs:string"/> <xs:element name="middle" type="xs:string" minOccurs="0"/> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:all> <xs:anyAttribute/> </xs:complexType> </xs:schema>
This highlights two change to all-groups: addition of wildcards and maxOccurs > 1. Which allows names such as:
<name xmlns="http://www.example.org/name/1"> <given>Dave</given> <family>Orchard</family> </name> <name xmlns="http://www.example.org/name/1"> <family>Orchard</family> <given>Dave</given> </name> <name xmlns="http://www.example.org/name/1"> <middle>Bryce</middle> <given>Dave</given> <family>Orchard</family> </name>
There are a number of other potential changes to all-groups which the WG is still considering.
Providing an option to allow the schema author to specify clustering semantics (in which all elements matching a given particle in the all-group must be together in the input, rather than interleave semantics)
Allowing all-groups to appear within choices and sequences.
Allowing choices and sequences (and nested all-groups?) to appear within all-groups.
Defining the extension of an all-group as adding new items to the all-group, rather than as producing a sequence consisting of the all-group followed by the new material.
The previous schemas allowed extra content that was already defined because the wildcard could match anything, such as:
<name xmlns="http://www.example.org/name/1"> <given>Dave</given> <family>Orchard</family> <given>Dave</given> </name>
We can preclude the "extra" occurances by using the negative wildcard to disallow certain elements, ie:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:any notQName="name:name name:given name:family" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="given" type="xs:string"/> <xs:any namespace="http://www.example.org/name/1" notQName="name:name name:given name:family" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="family" type="xs:string"/> <xs:any notNamespace="http://www.example.org/name/1" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
The first wildcard allows anything other than name:name, name:given, name:family. The 2nd wildcard allows any element in the http://www.example.org/name/1 namespace expect for name, given, family. The last wild card allows for any namespace other than the http://www.example.org/name/1 namespace.
It is possible to re-use the excluded QNames by use of a model group with a wildcard containing the QNames.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:group name="definedQNames"> <xs:sequence> <xs:any notQname="name:name name:given name:family"/> </xs:sequence> </xs:group> <xs:complexType name="name"> <xs:sequence> <xs:group ref="definedQNames"/> <xs:element name="given" type="xs:string"/> <xs:group ref="definedQNames"/> <xs:element name="family" type="xs:string"/> <xs:group ref="definedQNames"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
Many XML Languages use multiple namespaces. Imagine the name where the given and family are from different namespaces than the name with wildcards at the end. What wildcard should be there? Saying "##any" means already existing terms could be inserted. ##other only prevents items from the target namespace (name) from appearing. If we want to allow only elements that are not in the givenns, familyns, or name namespaces, we can use negative wildcards:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1" xmlns:givenns="http://www.example.org/name/given/1" xmlns:familyns="http://www.example.org/name/family/1"> <xs:complexType name="name"> <xs:sequence> <xs:element name="given" type="givenns:given"/> <xs:element name="family" type="familyns:family"/> <xs:any notNamespace="http://www.example.org/name/1 http://www.example.org/name/given/1 http://www.example.org/name/family/1" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
A common versioning scenario is to extend an existing namespace with new names, as mentioned in TAG finding (http://www.w3.org/2001/tag/doc/namespaceState.html). If we want to exclude existing terms from a namespace, we can also list them, as shown earlier but reprised in multi-ns:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:element name="given" type="givenns:given"/> <xs:element name="familY" type="familyns:family"/> <xs:any namespace="##any" notQName="name:name givenns:given familyns:family" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
This ends the description of the mechanisms that are in the WD. The following are under active discussion.
The previous schemas can be hard to read because of the wildcards sprinkled through the types. Also, the language designer has to remember to put the wildcards in everywhere. To solve this problem, we introduce default wildcards, as in:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent namespace="##any" processContents="lax"> <xs:sequence> <xs:element name="given" type="xs:string"/> <xs:element name="middle" type="xs:string" minOccurs="0"/> <xs:element name="family" type="xs:string"/> </xs:sequence> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
We see that this can become difficult to manage as the number of wildcards and definitions grows. If there were 1000 element definitions and another one was added, then potentially 1000 wildcards would need to be updated to preclude the new element. To help with this manageability issue, the Not In Schema wildcard specifies that any existing element is not allowed in the wildcard and is equivalent to the negative wildcard. For ease of authoring, the examples are based upon the default wildcard mentioned above.
The schema looks like:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent namespace="##nis" processContents="lax"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
The idea is that the excluded Qnames are the ones that are already defined. The schema looks like:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent namespace="##any" notQNames="##defined" processContents="lax"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
The idea is that the processing is the opposite of strict - whereas strict says must have the content, anti-strict means can't have the content. The schema looks like:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent namespace="##any" processContents="antistrict"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
There is some concern that the previous variants had the problem that a document that should be valid isn't valid because a type is "known". For example, a generational suffix might be defined in somebody's system unbeknownst to the name author. The solution is to say that the namespaces that are allowed and names excluded must be listed. The schema looks like:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent namespace="http://www.example.org/name/1 http://www.example.org/name/2 http://example.org/name/foo" notQNames="##defined" processContents="lax"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
DaveO Personal Note: I don't find this argument compelling. If somebody is sending a generational suffix that is "failing" validation then there is confusion over the definition of the suffix. The system with the generational suffix should say what definition of generational suffix they want to apply and where if there is any such confusion.
We acknowledged earlier that the use of wildcards in places other than the end of a contenet model meant that the existing type couldn't be used to extend the content model. If we restrict ourselves to wildcards at the end of a content model, then we can use type extension to add content to the content model, such as
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent namespace="##any" processContents="lax"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> <xs:complexType name="nameWithMiddle"> <xs:complexContent> <xs:extension base="name:name"> <xs:openContent namespace="##any" processContents="lax"> <xs:sequence> <xs:element name="middle" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:openContent> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="name" type="name:nameWithMiddle"/> </xs:schema>
This results in a type which has two wildcards: the first between family and middle, the 2nd after middle. It is roughly:
<xs:sequence> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="middle" type="xs:string" minOccurs="0"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence>
This may not be the desired approach because we may want to replace the trailing wildcard with the additional content. Currently, this replacement can only be done using Restriction:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="nameWithMiddle"> <xs:complexContent> <xs:restriction base="name:name" > <xs:openContent open="suffix" namespace="##any" processContents="lax"> <xs:sequence> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> <xs:element name="middle" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:openContent> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:element name="nameWithMiddle" type="name:nameWithMiddle"/> </xs:schema>
Note that the restriction forces us to replicate the content model of the restricted type. This does allow us to perform significant updates to the content model, for example
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:openContent open="true" namespace="##any" processContents="lax"> <xs:sequence> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:sequence> </xs:openContent> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> <xs:complexType name="MuchBetterName"> <xs:complexContent> <xs:restriction base="name:name" > <xs:openContent open="true" namespace="##any" processContents="lax"> <xs:sequence> <xs:element name="prefix" type="xs:string" minOccurs="0"/> <xs:element name="given" type="xs:string"/> <!-- ie David --> <xs:element name="familiarname" type="xs:string" minOccurs="0"/> <!-- ie Dave --> <xs:element name="middle" type="xs:string" minOccurs="0"/> <xs:element name="family" type="xs:string"/> <xs:element name="suffix" type="xs:string" minOccurs="0"/> <xs:element name="fullyWrittenName" type="xs:string" minOccurs="0"/> <!-- ie Henry S Truman --> </xs:sequence> </xs:openContent> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:element name="MuchBetterName" type="name:MuchBetterName"/> </xs:schema>
The previous example creates a new type, but can retain the element name. When a consumer receives the existing element name with an xsi:type specifying the new type, it may not know about the new type. A fallback from the xsi:type to the declared type allows a consumer can "cast" the type it does know about into the declared type.
<name xmlns="http://www.example.org/name/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="name:nameWithMiddle"> <given>Dave</given> <family>Orchard</family> <middle>Bryce</middle> </name>
If the consumer of this element didn't understand the xsi:type definition (name:nameWithMiddle), they could "cast" it to the declared type (name:name), resulting in roughly:
Place Holder:
Use wildcards not at the end when not worried about by-reference extension.
Use wildcards when allowing current or other ns:
Use fallback when items should be removed from PSVI or configurable
Use Negative wildcard to exclude specific items
Use NIS as a shorthand for negative wildcards
Use fallback Type when new type is sent
Note, the syntax used here-in is probably incorrect as it isn't maintained as closely as the in-scope mechanisms.
We notice that a primary concern of the not in schema wildcard is to ensure that the maxOccurs of the element isn't negated by the wildcard. It may be the case that we want to allow elements from outside the content model but in the schema to be added in a future version and we solely want to prevent maxOccurs violation. The "Not in Content mode" variant of negative wildcard allows, such as:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence anydefaultlocation="aroundall" anydefaultns="##nic" anydefaultprocesscontents="lax"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
It is often the case that new version authors do not wish to replicate the entire content model in restriction, can live with extension only at the end of the content model, and would prefer to just list the new content. One potential solution is to revise XML Schema's extension mechanism to specify that a trailing wildcard in a base type is replaced by the extension. ie:
<xs:complexType name="name"> <xs:sequence anydefaultlocation="atend" anydefaultns="##any"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:complexType name="nameWithMiddle"> <xs:complexContent> <xs:extensionRemovingTrailingWildcard base="name:name" > <xs:sequence anydefaultlocation="atend" anydefaultns="##any"> <xs:element name="middle" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:extensionRemovingTrailingWildcard> </xs:complexContent> </xs:complexType>
This proposed new extension would result in a content model of
Fallback allows replacement content to be inserted if an element type isn't defined. All the previous examples generally retain the extra content in the PSVI. One use of fallback is to "prune" the extra content from the PSVI, such as:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:complexType name="name"> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"> <xs:fallback/> </xs:any> <xs:element name="given" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"> <xs:fallback/> </xs:any> <xs:element name="family" type="xs:string"/> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"> <xs:fallback/> </xs:any> </xs:sequence> <xs:anyAttribute/> </xs:complexType> <xs:element name="name" type="name:name"/> </xs:schema>
In this example, any extensions will be pruned and will not be in the PSVI after fallback processing is applied.
Also see the following section for instance document based fallback.
The previous example creates a new type and preserved the existing name. Another possibility is that new element names will be created. When a consumer receives a new element name, it may not know about the new element name or type. An xsi:fallbackElement can be specified in the instance, and a consumer can "cast" the element it does know about into the xsi:fallbackElement.
<nameWithMiddle xmlns="http://www.example.org/name/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="name:nameWithMiddle" xsi:fallbackElement="name:name"> <given>Dave</given> <family>Orchard</family> <middle>Bryce</middle> </nameWithMiddle>
If the consumer of this element didn't understand the element definition, they could "cast" it to the fallbackElement, resulting in:
<name xmlns="http://www.example.org/name/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="name:nameWithMiddle" > <given>Dave</given> <family>Orchard</family> <middle>Bryce</middle> </name>
This would then combine with the fallback to Declared type as mentioned previously.
Let us explore multiple versions. Imagine a 3rd version of name is created with a suffix:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/name/1" elementFormDefault="qualified" xmlns:name="http://www.example.org/name/1"> <xs:element name="nameWithMiddleAndSuffix" type="name:nameWithMiddleAndSuffix"/> <xs:complexType name="nameWithMiddleAndSuffix"> <xs:complexContent> <xs:restriction base="name:nameWithMiddle" > <xs:sequence anydefaultlocation="atend" anydefaultns="##any"> <xs:element name="given" type="xs:string"/> <xs:element name="family" type="xs:string"/> <xs:element name="middle" type="xs:string" minOccurs="0"/> <xs:element name="suffix" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> </xs:schema>
There is a problem of chaining the fallback elements together. TBD. Does the following work?
<nameWithMiddleAndSuffix xmlns="http://www.example.org/name/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="name:nameWithMiddleAndSuffix" xsi:fallbackElement="name:nameWithMiddle name:name"> <given>Dave</given> <family>Orchard</family> <middle>Bryce</middle> </nameWithMiddleAndSuffix>