XML Page

Links

XML Schema: Primer (2nd Edition)
XML Schema: Structures (2nd Edition)
XML Schema: Datatypes (2nd Edition)
XML Schema: Component Designators (WD)

XML Schema FAQ

Question: How do I get a list with unconstrained order?

For example, suppose I want instances like:

<mylist><a/><b/><c/></mylist>
<mylist><b/><a/><c/></mylist>

Answer: Use the xsd:all or xsd:choice compositors

Create a complex type that uses the xsd:all instead of the xsd:sequence compositor. A limitation is that this must be a top level grouping, and you can only have 0 or 1 occurrences of each child.

<xsd:element name="mylist">
   <xsd:complexType>
      <xsd:all>
         <:xsd:element ref="a"/>
         <:xsd:element ref="b"/>
         <:xsd:element ref="c"/>
      </xsd:all>
   <xsd:/complexType>
</xsd:element>

If you want unbounded occurrences of each child, you can use a xsd:choice compositor instead. This will allow arbitrary numbers of a's, b's, and c's in any order. This will not, however, ensure that you have at least one of each child element.

<xsd:element name="mylist">
   <xsd:complexType>
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
         <:xsd:element ref="a"/>
         <:xsd:element ref="b"/>
         <:xsd:element ref="c"/>
      </xsd:all>
   <xsd:/complexType>
</xsd:element>

You may want to consider whether you really should define your content model this way. The ability for instances to have a different order for children is useful when the order is conveying some information. Many people are tempted into using the xsd:all compositor, however, when order means nothing at all, usually with the idea of making life easier for creators of instances. It doesn't always play out that way, however: remembering to put in all the required elements can be easier if there is a fixed order to remember. The xsd:sequence compositor can be used unless differences in order are actually meaningful.

Question: How do I get an attribute on an element of simple type?

For example, suppose I want instances like:

<height unit="meter">45.4</height>

Where the value 45.4 is a decimal?

Answer:

Create a complex type with simple content that extends decimal:

<xsd:complexType name="decimalWithUnitOfMeasure">
   <xsd:simpleContent>
      <xsd:extension base="xsd:decimal">
         <xsd:attribute name="unit" type="xsd:string" use="required"/>
      </xsd:extension>
   </xsd:simpleContent>
</xsd:complexType>

Question: How can I have different content models depending on the value of an attribute?

For example, suppose I have instances like:

<request-list>
  <request kind="collectionInfo">
     <collection name="MyCollection"/>
     <collection name="MyOtherCollection"/>
  </request>

  <request kind="userInfo">
     <user name="fred"/>
     <authentication type="basic" token="gAMABEA="/>
  </request>
</request-list>

Where requests of different kinds have different content models.

Answer:

The short answer is that you can't quite get there with XML Schemas as it stands today, in that the model is that you are either using the element name to distinguish types, or you are using the type to do so, i.e. via xsi:type. So what you are trying to do is replicate the effect of complex type identification through some vocabulary-specific attribute. Co-occurrence constraints are under consideration for 1.1 to address some of these kinds of things, but until then you can put in a non-schema constraint if you want to do this without changing anything.

The longer answer is that there are different patterns of vocabulary development enabled by XML Schemas:

Pattern 1: Same name, different types

Instance:

<request-list>
  <request kind="collectionInfo" xsi:type="collectionInfo">
     <collection name="MyCollection"/>
     <collection name="MyOtherCollection"/>
  </request>

  <request kind="userInfo" xsi:type="userInfo">
     <user name="fred"/>
     <authentication type="basic" token="gAMABEA="/>
  </request>
</request-list>

Schema:

<xsd:element name="request" type="requestType"/>

<xsd:complexType name="requestType" abstract="true"/>

<xsd:complexType name="collectionInfo">
  <xsd:complexContent>
    <xsd:extension base="requestType">
      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
        <xsd:element ref="collection"/>
      </xsd:sequence>
      <xsd:attribute name="kind" type="xsd:string" fixed="collectionInfo"/>
    </xsd:extension>
  </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="userInfo">
  <xsd:complexContent>
    <xsd:extension base="requestType">
      <xsd:sequence>
        <xsd:element ref="user"/>
        <xsd:element ref="authentication"/>
      </xsd:sequence>
      <xsd:attribute name="kind" type="xsd:string" fixed="userInfo"/>
    </xsd:extension>
  </xsd:complexContent>
</xsd:complexType>

<xsd:element name="request-list">
  <xsd:complexType>
     <xsd:sequence>
        <xsd:element ref="request" minOccurs="0" maxOccurs="unbounded"/>
     </xsd:sequence>
  </xsd:complexType>
</xsd:element>

Notes:

It would be possible, by introducing intermediate complexTypes, to have the base type (request) have the kind attribute and then restricting it to take the appropriate values. But the kind attribute is in fact entirely redundant with the xsi:type attribute, and could be dropped, giving us just:

<request-list>
  <request xsi:type="collectionInfo">
     <collection name="MyCollection"/>
     <collection name="MyOtherCollection"/>
  </request>

  <request xsi:type="userInfo">
     <user name="fred"/>
     <authentication type="basic" token="gAMABEA="/>
  </request>
</request-list>

Pattern 2: Different name, same 'kind'

Instance:

<request-list>
  <collectionInfo kind="collectionInfo">
     <collection name="MyCollection"/>
     <collection name="MyOtherCollection"/>
  </collectionInfo>

  <userInfo kind="userInfo">
     <user name="fred"/>
     <authentication type="basic" token="gAMABEA="/>
  </userInfo>
</request-list>

Schema:

<xsd:element name="request" type="requestType"/>

<xsd:complexType name="requestType" abstract="true"/>

<xsd:element name="collectionInfo" 
        substitutionGroup="request" type="collectionInfo"/>
<xsd:element name="userInfo" 
        substitutionGroup="request" type="userInfo"/>

<xsd:complexType name="collectionInfo">
  <xsd:extension base="requestType">
    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="collection"/>
    </xsd:sequence>
    <xsd:attribute name="kind" type="xsd:string" fixed="collectionInfo"/>
  </xsd:extension>
</xsd:complexType>

<xsd:complexType name="userInfo">
  <xsd:extension>
    <xsd:sequence>
      <xsd:element ref="user"/>
      <xsd:element ref="authentication"/>
    </xsd:sequence>
    <xsd:attribute name="kind" type="xsd:string" fixed="userInfo"/>
  </xsd:extension>
</xsd:complexType>

<xsd:element name="request-list">
  <xsd:complexType>
     <xsd:sequence>
        <xsd:element ref="request" minOccurs="0" maxOccurs="unbounded"/>
     </xsd:sequence>
  </xsd:complexType>
</xsd:element>

Notes:

It would also be possible to use choice groups instead of substitution groups in constructing the schema.

The same remarks apply as above. The kind attribute isn't helpful, and can be removed:

<request-list>
  <collectionInfo kind="collectionInfo">
     <collection name="MyCollection"/>
     <collection name="MyOtherCollection"/>
  </collectionInfo>

  <userInfo>
     <user name="fred"/>
     <authentication type="basic" token="gAMABEA="/>
  </userInfo>
</request-list>

Not that for more complex patterns of substitutability, it is possible to construct hierarchies of substitution groups. For example, MathML has an extensive array of operators of various arities and other relationships, where each operator in a class may occur in the same contexts, but the instances use the names of the operators, not attributes. This XML Schema for MathML makes use of hierarchical substitution to get this effect. Because XML Schema 1.0 only allows an element to be a member of one substitution group, there is a small amount of complexity in laying out this hierarchy. Multiple substitution groups in in view as an addition to XML Schema 1.1.