Complex Types

Complex Types and Content Models

A complex type allows attributes, children or both: an xs:sequence (in order), xs:choice (one of) or xs:all (any order), with minOccurs/maxOccurs defaulting to 1. xs:simpleContent adds attributes to text, mixed="true" allows text between children, ref reuses global elements, and xs:unique, xs:key and xs:keyref enforce identity:

catalog.xsd: complex types for the catalog, books and contributorsXML
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:include schemaLocation="types.xsd"/>
  <xs:element name="catalog" type="catalogType">
    <xs:unique name="uniqueSku"><xs:selector xpath="book/identifier"/><xs:field xpath="."/>
    </xs:unique>
  </xs:element>
  <xs:complexType name="catalogType"><xs:sequence>
    <xs:element name="header"><xs:complexType><xs:sequence>
      <xs:element name="sender" type="xs:string"/><xs:element name="sent" type="xs:dateTime"/>
      <xs:element name="records" type="xs:nonNegativeInteger"/>
    </xs:sequence></xs:complexType></xs:element>
    <xs:element name="book" type="bookType" maxOccurs="unbounded"/></xs:sequence>
    <xs:anyAttribute namespace="http://www.w3.org/XML/1998/namespace" processContents="skip"/>
  </xs:complexType>
  <xs:element name="identifier" type="idType"/>
  <xs:complexType name="bookType"><xs:sequence>
    <xs:element ref="identifier"/><xs:element name="title" type="xs:string"/>
    <xs:element name="contributor" type="contributorType" maxOccurs="unbounded"/>
    <xs:element name="subject" type="subjectType"/>
    <xs:element name="pages" type="xs:positiveInteger"/>
    <xs:element name="published" type="xs:gYear"/><xs:element name="summary" type="xs:string"/>
    <xs:element name="rating" type="ratingType" minOccurs="0"/>
    <xs:element name="supply"><xs:complexType><xs:sequence>
      <xs:element name="availability" type="availabilityType"/>
      <xs:element name="price" type="priceType"/></xs:sequence></xs:complexType></xs:element>
    </xs:sequence><xs:attribute name="id" type="xs:ID" use="required"/>
  </xs:complexType>
  <xs:complexType name="contributorType"><xs:sequence>
    <xs:element name="name" type="xs:string"/><xs:element name="sort-name" type="xs:string"/>
    </xs:sequence><xs:attribute name="role" type="roleType" use="required"/>
    <xs:attribute name="seq" type="xs:positiveInteger" default="1"/>
  </xs:complexType>
  <xs:complexType name="subjectType"><xs:simpleContent><xs:extension base="xs:string">
    <xs:attribute name="scheme" type="xs:token" use="required"/>
  </xs:extension></xs:simpleContent></xs:complexType>
  <xs:complexType name="idType"><xs:simpleContent><xs:extension base="xs:token">
    <xs:attribute name="type" type="xs:token" default="sku"/>
  </xs:extension></xs:simpleContent></xs:complexType>
  <xs:complexType name="priceType"><xs:simpleContent><xs:extension base="moneyType">
    <xs:attribute name="currency" type="xs:token" use="required"/>
  </xs:extension></xs:simpleContent></xs:complexType>
</xs:schema>

Every leaf is now typed (pages a positive integer, sent a timestamp), xs:anyAttribute admits xml:lang without fetching W3C's xml.xsd, and xs:unique catches a repeated SKU, which a DTD cannot express.