Complex types are used to define the content model and attributes of elements. This chapter introduces complex types. It covers the four content types (simple, element-only, mixed, and empty) and the use of element declarations, model groups, attribute declarations, and wildcards to define complex types.
Elements that have complex types have child elements or attributes. They may also have character content. Example 12–1 shows the elements size
, product
, letter
, and color
that have complex types. They have the four different content types that are described in this chapter (simple, element-only, mixed, and empty, respectively).
Attributes can never have complex types; they always have simple types. This makes sense, because attributes cannot themselves have children or attributes.
<size system="US-DRESS">10</size>
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
</product>
<letter>Dear <custName>Priscilla Walmsley</custName>...</letter>
<color value="blue"/>
Complex types may be either named or anonymous. Named types can be used by multiple element and attribute declarations. They are always defined globally (i.e., their parent is always schema
1) and are required to have a name that is unique among the types (both simple and complex) in the schema. The syntax to define a named complex type is shown in Table 12–1.
The name
of a complex type must be an XML non-colonized name, which means that it must start with a letter or underscore, and may only contain letters, digits, underscores, hyphens, and periods. You cannot include a namespace prefix when defining the type; it takes its namespace from the target namespace of the schema document. All of the examples of types in this book have the word “Type” at the end of their names, to clearly distinguish them from element names. However, this is a convention and not a requirement. You can even have a type definition and an element declaration using the same name, but this is not recommended because it can be confusing.
Example 12–2 shows the definition of the named complex type ProductType
, along with an element declaration that references it.
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="size" type="SizeType"/>
</xs:sequence>
</xs:complexType>
<xs:element name="product" type="ProductType"/>
Anonymous complex types, on the other hand, must not have names. They are always defined entirely within an element declaration, and may only be used once, by that declaration. Defining a type anonymously prevents it from ever being restricted, extended, redefined, or overridden. The syntax to define an anonymous complex type is shown in Table 12–2.
Example 12–3 shows the definition of an anonymous complex type within an element declaration.
<xs:element name="product">
<xs:complexType>
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="size" type="SizeType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
The question of whether to use named or anonymous types is covered in Section 8.2.3 on p. 133.
There are four different possible structures for the children of complexType
elements, representing four different methods of creating complex types:
• A single complexContent
child, which is used to derive a complex type from another complex type. It is covered in detail in the next chapter, Chapter 13.
• A single simpleContent
child, which is used to derive a complex type from a simple type. This is covered briefly in Section 12.3.1 of this chapter, and in more detail in the next chapter.
• A group (group
, all
, choice
, or sequence
) and/or attribute declarations. This is used to define a complex type without deriving it from any particular type. We will cover this method in this chapter.
• No content at all, in which case the type allows no attributes and no content.
The various declarations that make up the content of a complex type are known collectively as particles. Particles include local element declarations, element references, model groups (all
, choice
, or sequence
), named model group references, and element wildcards. All of these kinds of particles are described in detail in this chapter.
The contents of an element are the character data and child elements that are between its tags. The order and structure of the children allowed by a complex type are known as its content model. There are four types of content for complex types: simple, element-only, mixed, and empty. The content type is independent of attributes; all of these content types allow attributes. Figure 12–1 shows the decision tree needed to determine the appropriate content type. This section explains the four content types and provides an example of how each is represented in a schema.
Simple content allows character data only, with no children. Example 12–4 shows the element size
that has character data (the value 10
) but no child elements. Generally, the only thing that distinguishes a simple type from a complex type with simple content is that the latter may have attributes. If a size
element could never have a system
attribute, you could just give size
a simple type, as described in Chapter 8.
Example 12–5 shows a complex type definition that might be assigned to the size
element that appears in Example 12–4. It defines SizeType
whose character data content conforms to the simple type integer
. It extends integer
to add the attribute system
.
<size system="US-DRESS">10</size>
<xs:complexType name="SizeType">
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="system" type="xs:token"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Element-only content allows only children, with no character data content. Example 12–6 shows an element product
that has element-only content. It has four children: number
, name
, size
, and color
.
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<size system="US-DRESS">10</size>
<color value="blue"/>
</product>
Example 12–7 shows a complex type definition that might be used by the product
element declaration.
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="size" type="SizeType"/>
<xs:element name="color" type="ColorType"/>
</xs:sequence>
</xs:complexType>
Mixed content allows character data as well as child elements. This is most often used for freeform text such as letters and documents. Example 12–8 shows an element desc
with mixed content. Note that there is character data directly contained in the desc
element, as well as children i
, b
, and u
.
<desc>This is our <i>best-selling</i> shirt.
<b>Note: </b> runs <u>large</u>.</desc>
Example 12–9 shows a type definition that describes the letter
element shown in Example 12–8. To indicate that character data content is permitted, the complexType
element in Example 12–9 has an attribute mixed
that is set to true
. The default value for mixed
is false
, meaning that character data content is not permitted.
<xs:element name="desc" type="DescType"/>
<xs:complexType name="DescType" mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="i" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:element name="u" type="xs:string"/>
<!--...-->
</xs:choice>
</xs:complexType>
It is important to note that the character data that is directly contained in the desc
element (e.g., “This is our
”, “shirt
”, etc.) is not assigned a type. It is completely unrestricted in terms of its type and where (and whether) it appears. Therefore, you should not use mixed content types for data that you wish to constrain in any way.
Empty content allows neither character data nor child elements. Elements with empty content often have values in attributes. In some cases, they may not even have attributes; their presence alone is meaningful. For example, a <br/>
element in XHTML indicates a line break, without providing any data other than its presence. Example 12–10 shows an element color
with empty content.
<color value="blue"/>
Example 12–11 shows a type definition that might be assigned to the color
element in Example 12–10. Note that there is no special attribute in the complex type definition to indicate that the content is empty. The fact that only an attribute, with no content model, is specified for the complex type is enough to indicate this.
<xs:complexType name="ColorType">
<xs:attribute name="value" type="ColorValueType"/>
</xs:complexType>
Element declarations can be included in complex-type content models in three ways: as local element declarations, as references to global element declarations, and as wildcards.
Complex types can contain local element declarations. Such an element declaration specifies a name, a type, and other properties within the complex type. The scope of that element declaration is limited to the complex type within which it appears. Local element declarations are described in detail in Section 6.1.2 on p. 93. All of the prior examples in this chapter have local element declarations, as evidenced by the name
attributes of the element
elements.
Complex types can also contain references to global element declarations. Global element declarations themselves are covered in detail in Section 6.1.1 on p. 89. The syntax to reference a global element declaration is shown in Table 12–3. An element
element is used to make the reference, though it uses a ref
attribute instead of a name
attribute.
Example 12–12 shows four global element declarations, with the ProductType
definition referencing them through the ref
attribute. Note that the type
attribute appears in the global element declaration, while the minOccurs
attribute is in the element reference. Occurrence constraints (minOccurs
and maxOccurs
) may only appear within complex type definitions, that is, in element references or local element declarations but not in global element declarations.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="size" type="SizeType"/>
<xs:element name="color" type="ColorType"/>
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element ref="number"/>
<xs:element ref="name"/>
<xs:element ref="size" minOccurs="0"/>
<xs:element ref="color" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<!--...-->
</xs:schema>
For a detailed discussion of local or global element declarations see Section 6.1.3 on p. 95.
If two element declarations or references with the same name appear anywhere in the same complex type, they must have the same type. Example 12–13 shows a complex type definition that includes two declarations for name
. This content model represents “either number
or name
or both.” It is valid because both name
declarations refer to the exact same type, string
.
Example 12–14, on the other hand, is illegal because the two declarations of name
refer to different types.
<xs:complexType name="ProductType">
<xs:choice>
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="ProductType">
<xs:choice>
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:element name="name" type="xs:token"/>
</xs:choice>
</xs:complexType>
Anonymous types are never considered equal, even if they have identical content models. If either of the name
declarations used an anonymous type, it would automatically be illegal.
It is the qualified name that is relevant here. If one of the name
element names had been qualified, or both had been qualified with different namespace names, Example 12–14 would have been legal. This applies regardless of whether the element declarations are global or local.
It is only the type name that must be consistent. It is legal for the two name
element declarations to specify different default values, annotations, or other properties.
Model groups allow you to group child element declarations or references together to construct more meaningful content models. There are three kinds of model groups: all
groups, choice
groups, and sequence
groups.
Every complex type (except empty-content types) has exactly one model group child. This model group child contains the element declarations or references, or other model groups that make up the content model. Element declarations are never directly contained in the complexType
element.
A sequence
group is used to indicate that elements should appear in a specified order. In all previous examples, we specified a sequence
group using a sequence
element, whose syntax is shown in Table 12–4.
Example 12–15 shows a complex type definition that contains a sequence
group. All of the children (number
, name
, size
, and color
), if they appear, must appear in that order. The fact that the minOccurs
attribute of the size
and color
element declarations is set to 0
means that they are optional.
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="size" type="SizeType" minOccurs="0"/>
<xs:element name="color" type="ColorType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
Example 12–16 shows some valid instances of ProductType
. They are valid because the elements that are required (i.e., do not have their minOccurs
set to 0
) do appear and the elements that appear are in the correct order.
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<size system="US-DRESS">10</size>
<color value="blue"/>
</product>
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
</product>
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<color value="blue"/>
</product>
Example 12–17 shows an invalid instance of ProductType
. It is invalid because the elements appear in the wrong order.
<product>
<number>557</number>
<size system="US-DRESS">10</size>
<name>Short-Sleeved Linen Blouse</name>
<color value="blue"/>
</product>
You may not be concerned about the order in which an element’s children appear. However, some constraints will only work if you enforce an order. For example, in version 1.0, it is not possible to say that a product
may have one number
, one name
, and up to three color
children, in any order. You could use an all
group if you only want to allow each element once, or you could use a choice
group if you do not mind there being more than one number
or name
. You could also use a choice
group containing several sequence
groups to iterate over all the possible orders of the child elements, but this is rather cumbersome and becomes explosively more cumbersome as more children are added. In order to ensure that you will only have one number
and one name
, and allow more than one color
, the best approach is to enforce the order and use a sequence
group, as shown in Example 12–18.
Version 1.1 relaxes some constraints on all
groups, making it possible to express the above constraint without forcing a particular order. However, sequence
groups still have a slight advantage of clarity and ease of processing over all
groups.
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="color" type="ColorType" maxOccurs="3"/>
</xs:sequence>
</xs:complexType>
A choice
group is used to indicate that only one of the declared elements must appear. This is accomplished using a choice
element, whose syntax is shown in Table 12–5.
Example 12–19 shows a choice
group that specifies that any one of the elements (shirt
, hat
, or umbrella
) must appear.
<xs:complexType name="ItemsType">
<xs:choice>
<xs:element name="shirt" type="ShirtType"/>
<xs:element name="hat" type="HatType"/>
<xs:element name="umbrella" type="UmbrellaType"/>
</xs:choice>
</xs:complexType>
Example 12–20 shows some valid instances of ItemsType
. They are valid because each contains exactly one element declared in the choice
group. If more than one element appeared, or no elements at all appeared, it would be invalid.
<items>
<shirt>...</shirt>
</items>
<items>
<hat>...</hat>
</items>
A common use case for choice
groups is to allow any number of children to appear in any order. If, in our example above, we allowed the choice
group to repeat itself by setting its maxOccurs
attribute to unbounded
, as shown in Example 12–21, that would entirely change the meaning of the group. Now it allows any of the children, any number of times, in any order.
Example 12–22 shows a valid instance of the new definition of ItemsType
.
<xs:complexType name="ItemsType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="shirt" type="ShirtType"/>
<xs:element name="umbrella" type="UmbrellaType"/>
<xs:element name="hat" type="HatType"/>
</xs:choice>
</xs:complexType>
<items>
<shirt>...</shirt>
<hat>...</hat>
<umbrella>...</umbrella>
<shirt>...</shirt>
<shirt>...</shirt>
</items>
In Example 12–21, we also set the minOccurs
attribute of the choice
group to 0
. This means that items
would also be valid if it were completely empty.
Use of repeating choice
groups is especially common in narrative document-oriented XML, where child elements can be intermingled with character data content and their number and position needs to be very flexible. Example 12–9 on p. 265 showed a typical mixed-content complex type that uses a repeating choice group to allow any number of i
, b
, and u
elements to appear any number of times, in any order. Substitution groups, described in Chapter 16, are another approach to defining such a structure.
In order to specify more advanced content models, sequence
and choice
groups can be nested within each other as many levels deep as necessary. Example 12–23 shows a slightly more complicated definition of ProductType
. With this definition, number
must appear first, then name
, then any number of the properties (such as size
or color
) of the product, in any order. Note that the choice
group is inside the sequence
group, allowing you to combine the power of both kinds of model groups.
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="size" type="SizeType"/>
<xs:element name="color" type="ColorType"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
An all
group is used to indicate that elements can appear in any order. This is accomplished by using an all
element, whose syntax is shown in Table 12–6.
An all
group follows rules that are different from choice
and sequence
groups:
• In version 1.0, it can only contain element declarations and references, not other groups or wildcards. In version 1.1, this constraint has been relaxed, and an all
group can contain wildcards and group
references, as long as those groups also use all
.
• In version 1.0, for each element
it contains, maxOccurs
must be 1
, and minOccurs
may only be 0
or 1
. In version 1.1, this constraint has been eliminated; both minOccurs
and maxOccurs
can be greater than 1
, and maxOccurs
can be unbounded
.
• It cannot occur multiple times. For the all
element itself, maxOccurs
must be 1
, and minOccurs
may only be 0
or 1
.
• It cannot appear in other model groups. An all
group must be at the top level of the complex type.
Example 12–24 uses an all
group to represent the same basic structure for product
elements, with no specific order for the children.
<xs:complexType name="ProductType">
<xs:all>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="size" type="SizeType" minOccurs="0"/>
<xs:element name="color" type="ColorType" minOccurs="0"/>
</xs:all>
</xs:complexType>
Example 12–25 shows some valid instances of ProductType
, according to the new definition. The name
and number
elements are still required, but now they may appear in any order.
As mentioned above, an all
group cannot appear inside another model group. Example 12–26 is illegal because the all
group is inside a sequence
group.
<product>
<color value="blue"/>
<size system="US-DRESS">10</size>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
</product>
<product>
<name>Short-Sleeved Linen Blouse</name>
<number>557</number>
</product>
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:all>
<xs:element name="size" type="SizeType" minOccurs="0"/>
<xs:element name="color" type="ColorType" minOccurs="0"/>
</xs:all>
</xs:sequence>
</xs:complexType>
Named model groups may be referenced in complex type definitions, in order to make use of predefined content model fragments. Named model groups are described in detail in Section 15.2 on p. 386. Example 12–27 shows a reference to a named model group in a complex type definition.
<xs:complexType name="ProductType">
<xs:sequence>
<xs:group ref="DescriptionGroup"/>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
Like XML DTDs, XML Schema requires that content models be deterministic. In XML Schema, this is known as the Unique Particle Attribution (UPA) constraint. A schema processor, as it makes its way through the children of an instance element, must be able to find only one branch of the content model that is applicable, without having to look ahead to the rest of the children. The classic example is Example 12–28. It is intended to represent a choice among a
, b
, and a
followed by b
.
<xs:complexType name="AOrBOrBothType">
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
</xs:choice>
</xs:complexType>
This content model is nondeterministic because the processor, if it first encounters a
, will not know whether it should validate it against the first declaration of a
or the second declaration of a
without looking ahead to see if there is also a child b
. It may seem that it should not matter which a
declaration we are talking about; they both have the same type. However, they may have other properties that are different, such as default values, identity constraints, or annotations.
Example 12–29 represents the same desired content model in a deterministic way. There is only one declaration of a
. There are two declarations of b
, but distinguishing between them does not require looking ahead. If the processor encounters b
as the first child, it knows to use the second declaration of b
. If it encounters b
after a
, it uses the first declaration of b
.
In this example, the conflict is between two element declarations with the same name. However, there are also more subtle conflicts, such as those between
• Two element wildcards whose valid values overlap
• An element declaration and a wildcard for which it is a valid replacement1
• An element declaration and the head of its substitution group
<xs:complexType name="AOrBOrBothType">
<xs:choice>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:element name="b" type="xs:string"/>
</xs:choice>
</xs:complexType>
As with elements, attributes can be included in complex types as local declarations, as references to global declarations, or via attribute group references.
Within complex type definitions, attributes must be specified after the content model. The local attribute declarations, attribute references, and attribute group references may appear in any order, intermixed with each other. There is no significance to the ordering of attributes in XML.
It is illegal to define a complex type that contains two attribute declarations with the same qualified name. This is understandable, since XML forbids this. However, if two attribute declarations have the same local name but different namespace names, they may both appear in the same complex type.
Complex type definitions can contain local attribute declarations. This means that the attributes are declared (that is, given a name, a type, and other properties) within the complex type. The scope of that attribute declaration is limited to the complex type within which it appears. Local attribute declarations are described in detail in Section 7.2.2 on p. 117.
Example 12–30 shows adding a local attribute declaration to ProductType
. Note that the attribute declaration appears after the sequence
group that represents the content model.
<xs:complexType name="ProductType">
<xs:sequence>
<!--...-->
</xs:sequence>
<xs:attribute name="effDate" type="xs:date"
default="1900-01-01"/>
</xs:complexType>
Complex type definitions can also contain references to global attribute declarations. Global attribute declarations themselves are covered in detail in Section 7.2.1 on p. 115. The syntax used to reference a global attribute declaration is shown in Table 12–7.
The use
attribute may be used to indicate whether the attribute is required or optional. The value prohibited
is used only when restricting complex types. If required
is chosen, then a default or fixed value in the global attribute declaration are ignored.
The default
attribute may be used to add a default value, or to override the default
attribute in the global attribute declaration. This is true for attribute references only; an element reference cannot override the default value in a global element declaration.
The fixed
attribute may be used to add a fixed value, but it cannot override or remove a fixed value specified in the global attribute declaration. Only one of default
and fixed
may appear; they are mutually exclusive.
The inheritable
attribute may be used to indicate that the attribute is inheritable, as described in Section 7.6 on p. 126. If it is not specified, it defaults to the inheritable
value of the global attribute declaration, which itself defaults to false
.
Example 12–31 shows a complex type definition with a reference to a global attribute declaration. Note that the type
attribute is in the global attribute declaration. In this case, the default
attribute in the attribute reference overrides the default
attribute in the global attribute declaration.
For a detailed discussion of local or global attribute declarations see Section 7.2.3 on p. 119.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:attribute name="effDate" type="xs:date"
default="1900-01-01"/>
<xs:complexType name="ProductType">
<xs:sequence>
<!--...-->
</xs:sequence>
<xs:attribute ref="effDate" default="2000-12-31"/>
</xs:complexType>
</xs:schema>
Attribute groups may be referenced in complex type definitions, in order to make use of predefined groups of attributes. Attribute groups are described in detail in Section 15.3 on p. 392. Example 12–32 shows a complex type definition that references the attribute group IdentifierGroup
.
<xs:complexType name="ProductType">
<xs:sequence>
<!--...-->
</xs:sequence>
<xs:attributeGroup ref="IdentifierGroup"/>
<xs:attribute name="effDate" type="xs:date"/>
</xs:complexType>
In version 1.1, it is possible to indicate that an attribute group is the default attribute group by specifying its name in the defaultAttributes
attribute on the schema
element. If such a default attribute group is defined, those attributes will automatically be allowed for every complex type in the schema document, unless you specifically disallow it. To disallow it, use the attribute defaultAttributesApply="false"
to your complex type. Default attribute groups are described further in Section 15.3.3 on p. 399.
Wildcards allow for more flexibility in the content models and attributes defined in a complex type. There are two kinds of wildcards: element wildcards, which use the any
element, and attribute wildcards, which use the anyAttribute
element.
Element wildcards provide flexibility in which child elements may appear. Element wildcards are represented by any
elements, whose syntax is shown in Table 12–8. The elements in an instance that match the wildcard are referred to as replacement elements in this book.
The minOccurs
and maxOccurs
attributes control the number of replacement elements. This number represents how many total replacement elements may appear, not how many of a particular type or how many types. The number does not include child elements of the replacement elements.
Example 12–33 shows a complex type definition for ProductType
that includes an element wildcard allowing any number of replacement elements at the end of the content model.
<xs:element name="product" type="ProductType"/>
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:any minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="color" type="xs:string"/>
<xs:element name="desc" type="xs:string"/>
<xs:element name="size" type="xs:integer"/>
Example 12–34 is a valid product
instance. It has three replacement elements: two color
elements and a size
element, which can appear in any numbers and in any order.
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<color>blue</color>
<size>12</size>
<color>red</color>
</product>
The namespace
attribute allows you to specify what namespaces the replacement elements may belong to. It may have the value ##any
, ##other
, or a list of values.
If it is ##any
, the replacement elements can be in any namespace whatsoever, or in no namespace. This is the default setting if neither the namespace
nor the notNamespace
attribute have been specified.
If it is ##other
, the replacement elements can be in any namespace other than the target namespace of the schema document, but they must be in a namespace. If the schema document has no target namespace, the replacement elements can have any namespace, but they must have one.
Otherwise, the value of the namespace
attribute can be a whitespace-separated list of values that may include any or all of the following items:
• ##targetNamespace
to indicate that the replacement elements may be in the target namespace of the schema document
• ##local
to indicate that the replacement elements may be in no namespace
• Specific namespace names for the replacement elements
The namespace constraint applies only to the replacement elements. The children of each replacement element, if they exist, are then validated according to the type of the replacement element.
The processContents
attribute controls how much validation takes place on the replacement elements. It may have one of three values:
• If it is skip
, the schema processor performs no validation whatsoever, and does not attempt to find a schema document associated with the wildcard’s namespace. The replacement elements must, however, be well-formed XML and must be in one of the namespaces allowed by the wildcard.
• If it is lax
, the schema processor will validate replacement elements for which it can find declarations and raise errors if they are invalid. It will not, however, report errors on the elements for which it does not find declarations.
• If it is strict
, the schema processor will attempt to find a schema document associated with the namespace, and validate all of the replacement elements. If it cannot find the schema document, or the elements are invalid, it will raise errors. This is the default value.
Suppose our product
element can also contain an extended textual description that may run several paragraphs. This description is going to appear on the company’s website, and we want the text to be formatted using XHTML. Example 12–35 shows an element wildcard that will allow DescriptionType
to contain any elements that are part of the XHTML namespace.
<xs:complexType name="DescriptionType" mixed="true">
<xs:sequence>
<xs:any namespace="http://www.w3.org/1999/xhtml"
minOccurs="0" maxOccurs="unbounded"
processContents="skip"/>
</xs:sequence>
</xs:complexType>
Example 12–36 shows a description
element which has the type DescriptionType
.
Since the processContents
attribute is set to skip
, it is not necessary to provide any information about where to find the schema to validate the replacement elements. It is only necessary that the elements in the instance have names that are qualified with the XHTML namespace. In our example, we accomplish this by associating the xhtml
prefix with the XHTML namespace, and by prefixing all of the XHTML element names.
<catalog xmlns:xhtml="http://www.w3.org/1999/xhtml">
<description>
This shirt is the <xhtml:b>best-selling</xhtml:b> shirt in
our catalog! <xhtml:br/> Note: runs large.
</description>
<!--...-->
</catalog>
If we had chosen strict
for the value of processContents
, we would have to go further and tell the processor where to find the XHTML schema. We could do this by importing the XHTML namespace and schema into our schema, as described in Section 4.3.2 on p. 66.
Version 1.1 provides two additional attributes for wildcards that allow you to specify namespaces and names that are disallowed for replacement elements.
The notNamespace
attribute allows you to specify the namespaces that the replacement elements may not belong to. It is a whitespace-separated list of values that may include any or all of the following items:
• ##targetNamespace
to indicate that the replacement elements may not be in the target namespace of the schema document.
• ##local
to indicate that the replacement elements must be in a namespace.
• Specific disallowed namespace names for the replacement elements.
The notNamespace
and the namespace
attributes on wildcards are mutually exclusive. They cannot both be specified. If neither is specified, the replacement elements can be in any namespace.
The notQName
attribute allows you to disallow certain elements from being replacement elements. It is a whitespace-separated list of values that may include any or all of the following items:
• ##defined
, to disallow replacement elements whose names match global element declarations in the schema.
• ##definedSibling
, to disallow replacement elements whose names match declarations (local element declarations or element references) in the same complex type, i.e. that could be siblings of the replacement element.
• Specific names for the disallowed replacement elements, which may or may not actually be declared in the schema; if these names are in a namespace, they must be prefixed appropriately or use in-scope default namespace declarations to assign the namespace.
Example 12–37 shows the use of the notNamespace
and notQName
attributes, which can be used together or individually.
<xs:element name="product" type="ProductType"/>
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
<xs:any minOccurs="0" maxOccurs="unbounded"
notNamespace="http://www.w3.org/1999/xhtml"
notQName="##definedSibling desc size"
processContents="lax"/>
</xs:sequence>
</xs:complexType>
<xs:element name="color" type="xs:string"/>
<xs:element name="size" type="xs:integer"/>
Example 12–38 is a valid product
instance. It has three replacement elements: two color
elements and a random
element. Neither color
nor random
is in the prohibited namespace or in the list of prohibited names. The random
element is allowed even though it is not declared in the schema, because processContents
is set to lax
.
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<color>blue</color>
<random>not declared in the schema</random>
<color>red</color>
</product>
Example 12–39 is a product
instance where every replacement element shown is invalid. A size
element is disallowed from being a replacement element because it is listed in notQName
, as is desc
, even though there is no declaration for desc
in the schema. Also disallowed as replacement elements are number
and name
, since ##definedSibling
is specified. Finally, there can be no replacement elements from the XHTML namespace because that namespace is listed in notNamespace
.
<product xmlns:xhtml="http://www.w3.org/1999/xhtml">
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<size>12</size>
<desc>Our best-selling shirt</desc>
<number>12345</number>
<xhtml:p>Our best-selling shirt</xhtml:p>
</product>
Some XML vocabularies need to be very flexible about where they allow extension elements. To this end, version 1.1 allows you to specify an open content model, which is essentially an element wildcard that allows replacement elements to appear interleaved with other elements, without forcing the schema author to explicitly specify wildcards between every element declaration in a content model. An open content model can apply to a single complex type, or be declared as the default for complex types in a schema document.
An open content model for a single complex type is defined using an openContent
element, whose syntax is shown in Table 12–9. The openContent
element always appears before the content model. It contains a standard any
wildcard as defined in Section 12.7.1 on p. 285. The one difference is that the wildcard inside the openContent
cannot have minOccurs
and maxOccurs
specified; it is implied that any number of replacement elements can appear.
The openContent
element has a mode
attribute that indicates where the replacement elements can appear.
• If it is interleave
(the default), the replacement elements can appear intermingled with the elements explicitly declared in the content model.
• If it is suffix
, the replacement elements can only appear at the end of the content.
• If it is none
, no any
child appears within openContent
and the content model is not open (this is primarily used to override a default open content model).
The complex type in Example 12–40 contains an openContent
element that allows any element from any other namespace to appear interleaved in the instance.
<xs:element name="product" type="OpenProductType"/>
<xs:complexType name="OpenProductType">
<xs:openContent>
<xs:any namespace="##other" processContents="lax"/>
</xs:openContent>
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
Example 12–41 shows a valid instance, where the product
element contains elements from an extension namespace interleaved with the declared number
and name
elements. The number
and name
elements must still conform to the content model specified in the sequence
group.
<product xmlns:ext="http://datypic.com/extension">
<ext:something>an extension element</ext:something>
<number>557</number>
<ext:something_else>another extension element</ext:something_else>
<name>Short-Sleeved Linen Blouse</name>
<ext:something_else>another extension element</ext:something_else>
<ext:something>an extension element</ext:something>
</product>
To allow extension elements only at the end, simply add mode="suffix"
to the openContent
element, as shown in Example 12–42. This example also has different settings for the wildcard, namely that the replacement elements are being strictly validated and must not be in a namespace.
<xs:element name="product" type="OpenProductType"/>
<xs:complexType name="OpenProductType">
<xs:openContent mode="suffix">
<xs:any namespace="##local" processContents="strict"/>
</xs:openContent>
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="something" type="xs:string"/>
Example 12–43 is a valid instance, with the replacement elements now at the end. As with the previous example, multiple replacement elements may appear.
This example may not appear to be any different from simply including the wildcard at the end of the sequence group instead of in openContent
. However, it is subtly different in that extensions of this type will expect the replacement elements to appear at the end of the extended type, not right after the name
element. This is described further in Section 13.4.2.3 on p. 311.
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<something>an extension element</something>
<something>an extension element</something>
</product>
It is also possible in version 1.1 to specify a default open content model that can apply to any complex type in the schema that allows children (that is, any one with element-only or mixed content). This is accomplished using a defaultOpenContent
element, whose syntax shown in Table 12–10.
The defaultOpenContent
element works the same way as the openContent
element, containing an element wildcard and specifying a mode
attribute to indicate where the replacement elements can appear. However, since it applies to multiple complex types in a schema document, it appears at the top level of the schema, after any includes, imports, and overrides but before any component definitions. Example 12–44 is a schema that contains a defaultOpenContent
and two complex types to which it applies.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:defaultOpenContent mode="suffix">
<xs:any namespace="##local"/>
</xs:defaultOpenContent>
<xs:element name="catalog" type="CatalogType"/>
<xs:complexType name="CatalogType">
<xs:sequence>
<xs:element name="product" type="ProductType"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="something" type="xs:string"/>
</xs:schema>
A valid instance is shown in Example 12–45, where both the catalog
and product
elements can contain replacement elements. In this case, they must appear at the end, since the mode
is set to suffix
.
<catalog>
<product>
<number>557</number>
<name>Short-Sleeved Linen Blouse</name>
<something>an extension element</something>
<something>an extension element</something>
</product>
<something>an extension element</something>
<something>an extension element</something>
</catalog>
If a default open content model is defined, it is possible to override it in an individual complex type using the openContent
element with a mode="none"
attribute. In Example 12–46, CatalogType
will not have open content because it overrides the default, but ProductType
will.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:defaultOpenContent mode="suffix">
<xs:any namespace="##local"/>
</xs:defaultOpenContent>
<xs:element name="catalog" type="CatalogType"/>
<xs:complexType name="CatalogType">
<xs:openContent mode="none"/>
<xs:sequence>
<xs:element name="product" type="ProductType"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Note that the default open content model does not apply to complex types with simple content, since they do not allow children. By default, it does not apply to complex types with empty content, either. However, you can use an appliesToEmpty="true"
attribute on defaultOpenContent
to indicate that the default open content model should apply to complex types with empty content.
Attribute wildcards are used to allow flexibility as to what attributes may appear on elements of a particular complex type. Attribute wildcards are represented by anyAttribute
elements, whose syntax is shown in Table 12–11.
The namespace
, processContents
, notNamespace
, and notQName
attributes for attribute wildcards work exactly the same as for element wildcards described in Section 12.7.1 on p. 285. The only difference between attribute wildcards and element wildcards is that attribute wildcards cannot have minOccurs
and maxOccurs
specified. If an attribute wildcard is present, it is assumed that there may be zero, one, or many replacement attributes present.
Attribute wildcards in a complex type must appear after all of the attribute declarations, attribute references, and attribute group references. There can only be one attribute wildcard in each complex type definition.
Example 12–47 shows the definition of a type that allows any number of replacement attributes from any namespace other than the target namespace of the schema document.
<xs:complexType name="ProductType">
<xs:sequence>
<!--...-->
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>