- Introduction
- Constraining the any Attribute
- Inheritance
- Substitution Groups
- Global and Local Type Declarations
- Conclusion
Global and Local Type Declarations
As with classes in object-oriented programming, you need to create instances of XML Schema types to do real work such as moving XML-encoded messages between web services. In this section, we'll examine two means of creating instances of types: using global types and declaring local types.
You've already seen examples of both of global (schema-scoped) and local (element-scoped) type declarations throughout the previous sections. A global type definition occurs where we embed a type directly as a child of the <schema> element of a schema. Conversely, a local type is declared as the child of an <element> element, which is a direct child of the <schema> element (see Listing 7).
Listing 7 Global and Local Type Declarations
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <!-- A Global Type --> <xs:complexType name="CardType"> <xs:sequence> <xs:element name="card-type"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="Visa"/> <xs:enumeration value="MasterCard"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="expiry"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{2}-[0-9]{2}"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="number"> <xs:simpleType name="CardNumberType"> <xs:restriction base="xs:string"> <xs:pattern value="[0-9]{4} [0-9]{4} [0-9]{4} [0-9]{4}"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="holder" type="xs:string"/> </xs:sequence> </xs:complexType> <!-- A local type --> <xs:element name="debit-card"> <xs:complexType> <xs:complexContent> <xs:extension base="CardType"> <xs:attribute name="issue" type="xs:positiveInteger"/> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> <!-- Another local type --> <xs:element name="wallet"> <xs:complexType> <xs:sequence> <xs:element name="credit-card" type="CardType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="debit-card" ref="debit-card" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
The distinction between the two types is important. Global types such as CardType in Listing 7 are globally visible, and thus are available within the namespace where they're declared and in other namespaces. They can be extended, and generally behave as we would expect classes to behave in an object-oriented programming language. Instances of global types are created by constructing an element whose type attribute refers to that particular global type's name. This is shown in Listing 7 with this element:
<xs:element name="credit-card" type="CardType" minOccurs="0" maxOccurs="unbounded"/>
which defines that an instance of the CardType type can be present any number of times in a wallet element.
On the other hand, local types are declared inline with an element (such as debit-card and wallet in Listing 7). While the element itself is visible to other elements and types, its implementing type is not, and therefore it's not extendable by other typesin fact, the implementing type doesn't even have a name so that you can refer to it.
When declaring a local type, it can subsequently be referred to only by its enclosing element name, and its content cannot be extended. In programming terms, this is similar to a component whose API is known, but whose type is anonymous and whose internal structure is a black box. This is shown in Listing 7 where the wallet (itself a local type) is defined as containing any number of instances of the debit-card local type via the ref attribute, like this:
<xs:element name="debit-card" ref="debit-card" minOccurs="0" maxOccurs="unbounded"/>
Whether to declare types globally or locally depends on your intended use for those types. If you intend for those types to form part of a type hierarchy, they should be declared globally so that they can be extended. If you intend for a type to support instances only within XML documents, declare it locally.
A good rule for developing content models is to type hierarchies with global types, but to create local type declarations at the leaf nodes of those hierarchies. Thus, within the hierarchy you have the full flexibility supplied by global types, yet the "interface" presented to users of that hierarchy is a collection of element declarations against which XML documents can be validated.