We will start by looking at complex types containing simple content because they are closest to simple types, which we've seen recently, and they also provide an easier transition to the more complex world of complex contents. We will not discuss the creation and derivation of simple types, already covered in Chapter 5, "Creating Simple Datatypes", but instead will focus on complex types' simple content models (i.e., elements having only text nodes and attributes) and study how they are created and derived.
Complex types with simple content models are created by adding a list of attributes to a simple type. The operation of adding attributes to a simple type to create a simple content complex type is called an extension of the simple type. The syntax is straightforward and we have already seen examples of such creation in Chapter 4, "Using Predefined Simple Datatypes":
<xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:extension base="string255"> <xs:attribute ref="lang"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element>
The only things that need to change here are that the definition of the simple type cannot be directly embedded in the xs:extension(complex content) and that it needs to be referenced through its base attribute.
This same syntax, with the same meaning, can be used to create global complex types, which can be used to define elements:
<xs:complexType name="tokenWithLang"> <xs:simpleContent> <xs:extension base="xs:token"> <xs:attribute ref="lang"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:element name="title" type="tokenWithLang"/>
Complex types provide a number of options for extending simple content models.
Derivation by extension is reserved for complex types and has no equivalent for simple types. It increases the number of child node elements or attributes allowed or expected in the complex type. For simple content complex types, child elements cannot be added and we stay with an extension that is identical to the method used to create a simple content complex type from a simple type. To add an attribute to the complex type tokenWithLang, just shown in the previous example, we could write:
<xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:extension base="tokenWithLang"> <xs:attribute name="note" type="xs:token"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element>
The derivation by restriction of simple content complex types is a feature at the border between the two parts of W3C XML Schema (Part 1: Structure and Part 2: Datatypes). It's also very similar to the derivation by restriction of simple datatypes, discussed in Chapter 6, "Using Regular Expressions to Specify Simple Datatypes". The only difference between the derivations by restriction in these two contexts is that the derivation by restriction of a simple content complex type allows not only restriction of the scope of the text node, but also the restriction of the scope of the attribute. This restriction follows the same principle as the restriction of a simple type: any instance structure deemed valid per the restricted type must also be valid per the base type (with the exception already mentioned for the xs:whiteSpace facet).
The syntax used to restrict the text child is the same as the syntax used to derive simple types by restriction. The facets are the same as well. These facets must be followed by the new list of attributes, which may have different types as long as they are derived from the types of the attributes from the base type. Attributes that are not mandatory in the base type can be specified in the new list as "prohibited," and attributes that are not included are considered unchanged. Following are some examples of derivations that start from a simple content datatype equivalent to the content model just shown:
<xs:complexType name="tokenWithLangAndNote"> <xs:simpleContent> <xs:extension base="xs:token"> <xs:attribute name="lang" type="xs:language"/> <xs:attribute name="note" type="xs:token"/> </xs:extension> </xs:simpleContent> </xs:complexType>
We can first show how to restrict the length of the text node, as we've done for simple types:
<xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:restriction base="tokenWithLangAndNote"> <xs:maxLength value="255"/> <xs:attribute name="lang" type="xs:language"/> <xs:attributename="note" type="xs:token"/> </xs:restriction> </xs:simpleContent> </xs:complexType> </xs:element>
To remove the note attribute from the element title, we declare note to be prohibited in the list of attributes in the restriction:
<xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:restriction base="tokenWithLangAndNote"> <xs:maxLength value="255"/> <xs:attribute name="lang" type="xs:language"/> <xs:attribute name="note" use="prohibited"/> </xs:restriction> </xs:simpleContent> </xs:complexType> </xs:element>
We can also restrict the datatype by restricting its attributes. For instance, if we want to restrict the number of possible languages, we can do it directly in the definition of the lang attribute in the derived type:
<xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:restriction base="tokenWithLangAndNote"> <xs:maxLength value="255"/> <xs:attribute name="lang"> <xs:simpleType> <xs:restriction base="xs:language"> <xs:enumeration value="en"/> <xs:enumeration value="es"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:restriction> </xs:simpleContent> </xs:complexType> </xs:element>
Despite apparent similarities, derivations by extension and restriction do not have much more in common than deriving new simple content types from base types! Derivation by extension can only add new attributes. It can neither change the datatype of the text node nor the type of an attribute defined in its base type. Derivation by restriction appears to be more flexible and can restrict the datatype of the text node and of the attributes of the base type. It can also remove attributes that are not mandatory in its base type.
Copyright © 2002 O'Reilly & Associates. All rights reserved.