You can specify the content model for an ElementType by using <element> to reference other ElementTypes. For example:
<Schema xmlns="urn:schemas-microsoft-com:xml-data">
<ElementType name="title" content="textOnly"/>
<ElementType name="authors" content="textOnly"/>
<ElementType name="pages" content="textOnly"/>
<ElementType name="book" order="seq" content="eltOnly">
<element type="title" />
<element type="authors" />
<element type="pages" />
</ElementType>
</Schema>
In the above example, content of a "book" element is defined to be the sequence of "title", "author" and "pages" elements. This allows you to write the following valid XML document:
<book xmlns="x-schema:book-schema.xml">
<title>Applied XML: A Toolkit for Programmers</title>
<authors>Alex Ceponkus and Faraz Hoodbhoy</authors>
<pages>474</pages>
</book>
This is a very simple case. There are a number of mechanisms in XML Schema that allow you to build more complex content models, including being able to group elements and define cardinality.
The most important innovation for content models in XML Schema is that content models are "open" by default. An open content model enables additional elements and/or attributes to be present within an element without having to declare each and every element in the XML Schema. This provides an extensibility mechanism not present when using Document Type Definitions (DTDs). For example:
<book xmlns="x-schema:book-schema.xml" xmlns:x="urn:some-new-namespace">
<title x:id="123">Applied XML: A Toolkit for Programmers</title>
<authors>Alex Ceponkus and Faraz Hoodbhoy</authors>
<pages>474</pages>
<x:publisher>Wiley Computer Publishing</x:publisher>
</book>
The following constraints apply on what is allowed in an open content model:
You can change this default behavior and specify a closed content model in instances where an open content model is not desired. In this case the model attribute can be used on the ElementType. For example:
<ElementType name="book" model="closed">
This indicates that a "book" element can only contain the content specified—"title," "author," and "pages" elements. In this case the above <book> example with the extended elements will not validate.
An element can contain text, other elements, a mixture of text and elements, or nothing at all. Use the content attribute to specify what the element will contain. Possible values are "textOnly", "eltOnly", "empty", and "mixed". For example, to indicate that an element contains text but no sub-elements, write:
<ElementType name="street" content="textOnly" />
Content for an element can also be limited to contain only sub-elements. For example:
<ElementType name="PurchaseOrder" content="eltOnly">
The value "empty" for content indicates that text and sub-elements are not allowed. The value "mixed" allows both text and sub-elements.
If an ElementType has a datatype specified such as date, number, etc., then "textOnly" is implied, and not required.
The minOccurs and maxOccurs attributes specify how many times an element can appear within another element.
<element type="Item" maxOccurs="*" />
The maxOccurs attribute is a constraint rule, specifying the maximum number of times that a sub-element may appear. Valid values for maxOccurs include integers and "*", which indicates that an unrestricted number of elements may appear. The default value for maxOccurs is "1"; however, when content="mixed", the default value is "*".
Similarly, you can specify a minimum number of times a sub-element may appear with minOccurs. For example, to make a sub-element optional, set minOccurs to "0". The default value for minOccurs is 1.
These attributes can be used for both element and group declarations.
The order attribute specifies whether sub-elements are required to appear in a certain order, and if only one sub-element of a set can appear.
The "seq" value indicates that sub-elements must appear in the order listed in the schema. For example:
<ElementType name="PurchaseOrder" order="seq">
The "one" value specifies that only one sub-element can be used from a list of sub-elements. For example, to specify that an "Item" element may contain either a "product" element or a "backOrderedProduct" element, but not both:
<ElementType name="Item" order="one">
<element type="product" />
<element type="backOrderedProduct" />
</ElementType>
The "many" value specifies that the sub-elements may appear in any order, and in any quantity.
The default value for order is "seq" when the content attribute is set to "eltOnly", and the default is "many" when content is set to "mixed".
The group element enables you to specify constraints on a specific set of sub-elements. For example, to indicate that the "Item" element has either a "product" or a "backOrderedProduct" element, and then a "quantity" and "price", you can use the following XML:
<ElementType name="Item">
<group order="one">
<element type="product" />
<element type="backOrderedProduct" />
</group>
<element type="quantity"/>
<element type="price"/>
</ElementType>
The group element accepts the order, minOccurs, and maxOccurs attributes.
Attributes are more limited in some ways than elements. For instance, attributes cannot contain sub-elements, and you cannot require attributes to appear in any particular order; nor can you pose alternatives, such as a "product" or a "backOrderedProduct". You can specify whether an attribute is required or optional, but an attribute may only appear once per element.
However, attributes have some capabilities that elements do not: attributes may limit their legal values to a small set of strings, and may indicate a value to be inferred if the attribute is omitted from an element. Most importantly, different element types may have attributes with the same name. These attributes are considered to be independent and unrelated.
The following example specifies that the attribute is required:
<AttributeType name="shipTo" dt:type="idref" required="yes"/>
The following limits the value of an attribute to words from a small list:
<AttributeType name="priority" dt:type="enumeration" dt:values="high medium low" />
To give a default value to an attribute (that is, a value that an application should infer if the attribute is not present in the document instance) use the default attribute, as follows:
<AttributeType name="quantity" dt:type="int">
<attribute type="quantity" default="1"/>