Using W3C XML Schema
by Eric van der Vlist
|
Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9
Building Usable -- and Reusable -- Schemas
Perhaps the first step in writing reusable schemas is to document them. W3C XML Schema provides an alternative to XML comments (for humans) and processing instructions (for machines) that might be easier to handle for supporting tools.
Human readable documentation can be defined by xs:documentation
elements, while information targeted to applications should be included in
xs:appinfo elements. Both elements need to be included in an
xs:annotation element and accept optional xml:lang
and source attributes and any content type. The source attribute is a URI
reference that can be used to indicate the purpose of the comment documentation
or application information.
The xs:annotation elements can be added at the beginning of most schema constructions, as shown in the example below. The appinfo section demonstrates how custome namespaces and schemes might allow the binding of an element to a Java class from within the schema.
<xs:element name="book"> <xs:annotation> <xs:documentation xml:lang="en"> Top level element. </xs:documentation> <xs:documentation xml:lang="fr"> Element racine. </xs:documentation> <xs:appinfo source="http://example.com/foo/"> <bind xmlns="http://example.com/bar/"> <class name="Book"/> </bind> </xs:appinfo> </xs:annotation>
Composing schemas from multiple files
For those who want to define a schema using several XML documents -- either to split a large schema, or to use libraries of schema snippets -- W3C XML Schema provides two mechanisms for including external schemas.
The first one, xs:include, is similar to a copy and paste of
the definitions of the included schema: it's an inclusion and as such it
doesn't allow to override the definitions of the included schema. It can be
used this way:
<xs:include schemaLocation="character.xsd"/>
The second inclusion mechanism, xs:redefine, is similar to xs:include, except that it lets you
redefine declarations from the included schema.
<xs:redefine schemaLocation="character12.xsd">
<xs:simpleType name="nameType">
<xs:restriction base="xs:string">
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:redefine>
Note that the declarations that are redefined must be placed in the
xs:redefine element.
We've already seen many features that can be used together with
xs:include and xs:redefine to create libraries of
schemas. We've seen how we can reference previously defined elements, how we
can define datatypes by derivation and use them, how we can define and use
groups of attributes. We've also seen the parallel between elements and
objects, and datatypes and classes. There are other features borrowed from
object oriented designs that can be used to create reusable schemas.
Abstract types
The first of these features derived from object oriented design is the
substitution group. Unlike the features we've seen so far, a substitution group
is not defined explicitly through a W3C XML Schema element, but through
referencing a common element (called the head) using a
substitutionGroup attribute.
The head element
doesn't hold any specific declaration but must be global. All the elements within a substitution
group need to have a type that is either the same type as the head element or can be derived
from it. Then they can all be used in place of the head element. In the following example, the element surname can be used anywhere an element name has been defined.
<xs:element name="name" type="xs:string"/> <xs:element name="surname" type="xs:string" substitutionGroup="name" />
Now, we can also define a generic name-elt element, head of a
substitution group, that shouldn't be used directly, but in one of its derived
forms. This is done through declaring the element as abstract, analogous to
abstract classes in object oriented languages. The following example defines
name-elt as an abstract element that should be replaced either by
name or surname everywhere it is referenced.
<xs:element name="name-elt" type="xs:string" abstract="true"/> <xs:element name="name" type="xs:string" substitutionGroup="name-elt"/> <xs:element name="surname" type="xs:string" substitutionGroup="name-elt"/>
Final types
We could, on the other hand, wish to control derivation performed on a datatype.
W3C XML Schema supports this through the final attribute in a xs:complexType, xs:simpleType or
xs:element element. This attribute can take the values restriction, extension and #all to
block derivation by restriction, extension or any derivation. The following snippet would, for instance,
forbid any derivation of the characterType complex type.
<xs:complexType name="characterType" final="#all">
<xs:sequence>
<xs:element name="name" type="nameType"/>
<xs:element name="since" type="sinceType"/>
<xs:element name="qualification" type="descType"/>
</xs:sequence>
</xs:complexType>
In addition to final, a more fine-grained mechanism is provided
to control the derivation of simple types that operate on each facet. Here, the attribute is
called fixed, and when its value is set to true, the facet cannot be further modified (but
other facets can still be added or modified). The following example prevents the size of our
nameType simple type to be redefined:
<xs:simpleType name="nameType">
<xs:restriction base="xs:string">
<xs:maxLength value="32" fixed="true"/>
</xs:restriction>
</xs:simpleType>