Chapter 12. Complex types

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.

12.1. What are 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.

Example 12–1. Elements with complex types


<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"/>


12.2. Defining complex types

12.2.1. Named complex types

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 schema1) 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.

Table 12–1. XSD Syntax: named complex type definition

Image
Image

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.

Example 12–2. Named complex type


<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"/>


12.2.2. Anonymous complex types

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.

Table 12–2. XSD Syntax: anonymous complex type definition

Image

Example 12–3 shows the definition of an anonymous complex type within an element declaration.

Example 12–3. Anonymous complex type


<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.

12.2.3. Complex type alternatives

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.

12.3. Content types

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.

Image

Figure 12–1. Content type decision tree

12.3.1. Simple content

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.

Example 12–4. Instance element with simple content


<size system="US-DRESS">10</size>


Example 12–5. Complex type with simple content


<xs:complexType name="SizeType">
  <xs:simpleContent>
    <xs:extension base="xs:integer">
      <xs:attribute name="system" type="xs:token"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>


12.3.2. Element-only content

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.

Example 12–6. Instance element with element-only content


<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.

Example 12–7. Complex type with element-only content


<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>


12.3.3. Mixed content

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.

Example 12–8. Instance element with mixed content


<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.

Example 12–9. Complex type with mixed content


<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.

12.3.4. Empty content

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.

Example 12–10. Instance element 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.

Example 12–11. Complex type with empty content


<xs:complexType name="ColorType">
  <xs:attribute name="value" type="ColorValueType"/>
</xs:complexType>


12.4. Using element declarations

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.

12.4.1. Local element declarations

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.

12.4.2. Element references

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.

Table 12–3. XSD Syntax: element reference

Image

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.

Example 12–12. Element references


<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.

12.4.3. Duplication of element names

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.

Example 12–13. Legal duplication of element names


<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>


Example 12–14. Illegal duplication of element names


<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.

12.5. Using model groups

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.

12.5.1. sequence groups

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.

Table 12–4. XSD Syntax: sequence group

Image

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.

Example 12–15. A sequence group


<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.

Example 12–16. Valid instances of ProductType


<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.

Example 12–17. Invalid instance of ProductType


<product>
  <number>557</number>
  <size system="US-DRESS">10</size>
  <name>Short-Sleeved Linen Blouse</name>
  <color value="blue"/>
</product>


12.5.1.1. Design hint: Should I care about the order of elements?

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.

image

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.

image

Example 12–18. Enforcing order for better constraints


<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>


12.5.2. choice groups

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.

Table 12–5. XSD Syntax: choice group

Image

Example 12–19 shows a choice group that specifies that any one of the elements (shirt, hat, or umbrella) must appear.

Example 12–19. A choice group


<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.

Example 12–20. Valid instances of ItemsType


<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.

Example 12–21. A repeating choice group


<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>


Example 12–22. Valid instance of ItemsType


<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.

12.5.3. Nesting of sequence and choice groups

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.

Example 12–23. Multiple nested 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>


12.5.4. all groups

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.

Table 12–6. XSD Syntax: all group

Image

An all group follows rules that are different from choice and sequence groups:

image

• 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.

image

• 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.

Example 12–24. An all group


<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.

Example 12–25. Valid instances of ProductType using an all 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>


Example 12–26. An illegal all group


<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>


12.5.5. Named model group references

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.

Example 12–27. Complex type with a named model group reference


<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>


12.5.6. Deterministic content models

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.

Example 12–28. Illegal nondeterministic content model


<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

Example 12–29. Deterministic content model


<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>


12.6. Using attribute declarations

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.

12.6.1. Local attribute declarations

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.

Example 12–30. Local attribute declaration


<xs:complexType name="ProductType">
  <xs:sequence>
    <!--...-->
  </xs:sequence>
  <xs:attribute name="effDate" type="xs:date"
                default="1900-01-01"/>
</xs:complexType>


12.6.2. Attribute references

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.

Table 12–7. XSD Syntax: attribute reference

Image

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.

image

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.

image

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.

Example 12–31. Attribute reference


<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>


12.6.3. Attribute group references

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.

Example 12–32. Complex type with attribute group reference


<xs:complexType name="ProductType">
  <xs:sequence>
    <!--...-->
  </xs:sequence>
  <xs:attributeGroup ref="IdentifierGroup"/>
  <xs:attribute name="effDate" type="xs:date"/>
</xs:complexType>


image

12.6.4. Default attributes

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.

image

12.7. Using wildcards

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.

12.7.1. Element wildcards

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.

Table 12–8. XSD Syntax: element wildcard

Image
Image

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.

Example 12–33. Using an element wildcard


<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.

Example 12–34. Instance with replacement elements


<product>
  <number>557</number>
  <name>Short-Sleeved Linen Blouse</name>
  <color>blue</color>
  <size>12</size>
  <color>red</color>
</product>


12.7.1.1. Controlling the namespace of replacement elements

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.

12.7.1.2. Controlling the strictness of validation

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.

Example 12–35. Complex type with element wildcard


<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.

Example 12–36. Instance with processContents of skip


<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.

image
12.7.1.3. Negative wildcards

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.

Example 12–37. Negative wildcards


<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.

Example 12–38. Instance conforming to the schema with negative wildcards


<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.

Example 12–39. Invalid instance with disallowed namespaces and names


<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>


12.7.2. Open content models

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.

12.7.2.1. Open content in a complex type

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.

Table 12–9. XSD Syntax: open content

Image

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.

Example 12–40. Defining an interleaved open content model


<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.

Example 12–41. Instance of an interleaved open content model


<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.

Example 12–42. Defining a suffix open content model


<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.

Example 12–43. Instance of a suffix open content model


<product>
  <number>557</number>
  <name>Short-Sleeved Linen Blouse</name>
  <something>an extension element</something>
  <something>an extension element</something>
</product>


12.7.2.2. Default open content

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.

Table 12–10. XSD Syntax: default open content

Image

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.

Example 12–44. Defining a default open content model


<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.

Example 12–45. Instance using default open content model


<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.

Example 12–46. Overriding a default open content model


<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.

image

12.7.3. Attribute wildcards

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.

Table 12–11. XSD Syntax: attribute wildcard

Image

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.

Example 12–47. Complex type with attribute wildcard


<xs:complexType name="ProductType">
  <xs:sequence>
    <!--...-->
  </xs:sequence>
  <xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.185.69