Using W3C XML Schema - Part 2
by Eric van der Vlist
|
Pages: 1, 2, 3, 4, 5
Building Usable -- and Reusable -- Schemas
|
Table of Contents |
|
Content Types |
Perhaps the first step in writing reusable schemas is to document them. W3C XML Schema provides an alternative to XML comments and processing instructions that might be easier to handle for supporting tools.
Human readable documentation can be defined by
xsd:documentation elements, while information targeted at
applications should be included in xsd:appinfo elements. Both
elements must be included in an xsd:annotation element. They
accept optional xml:lang and source attributes.
The source attribute is a URI reference that can be used to
indicate the purpose of the appinfo to the processing application.
The xsd:annotation elements can be added at the beginning of
most schema constructs as shown in example below. The appinfo section
demonstrates how custom namespaces and schemes might allow the binding of an
element to a Java class from within the schema.
<xsd:element name="book">
<xsd:annotation>
<xsd:documentation xml:lang="en">
Top level element.
</xsd:documentation>
<xsd:documentation xml:lang="fr">
Element racine.
</xsd:documentation>
<xsd:appinfo source="http://example.com/foo/">
<bind xmlns="http://example.com/bar/">
<class name="Book"/>
</bind>
</xsd:appinfo>
</xsd:annotation>
...
Composing schemas from multiple files
For those who want to define a schema using several XML documents -- either to split up a large schema or to use libraries of schema snippets -- W3C XML Schema provides two mechanisms for including external schemas.
The first, xsd: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 any overriding of definitions of the included schema. It can
be used in this way:
<xsd:include schemaLocation="character.xsd"/>
The second inclusion mechanism, xsd:redefine, is similar to
xsd:include, except that it lets you redefine the declarations
from the included schema.
<xsd:redefine schemaLocation="character12.xsd"> <xsd:simpleType name="nameType"> <xsd:restriction base="xsd:string"> <xsd:maxLength value="40"/> </xsd:restriction> </xsd:simpleType> </xsd:redefine>
Note that the declarations that are redefined must be placed in
the xsd:redefine element.
We've already seen many features that can be used together with
xsd:include and xsd: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; and 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 design that can be used to create reusable
schemas.
Abstract types
The first feature derived from object oriented design is the substitution
group. Unlike the features we've seen so far, a substitution group isn't
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.
<xsd:element name="name" type="xsd:string"/> <xsd:element name="surname" type="xsd:string" substitutionGroup="name" />
Now we can also define a generic "name-elt" element, head of a
substitution group, that couldn't be used directly but should be used in one
of its derived forms. This is done through declaring the element as
abstract, analagously to abstract classes in object oriented languages. The
following example defines name-elt as an abstract element that
should be replaced by either name or surname everywhere it is
referenced.
<xsd:element name="name-elt" type="xsd:string" abstract="true"/> <xsd:element name="name" type="xsd:string" substitutionGroup="name-elt" /> <xsd:element name="surname" type="xsd: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 though the final
attribute in an xsd:complexType or xsd: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.
<xsd:complexType name="characterType" final="#all">
The final attribute can operate only on elements and complex
types. W3C XML Schema provides a fine-grained mechanism that operates on
each facet to control the derivation of simple types. This 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 prevents the size of our nameType simple
type from being redefined.
<xsd:simpleType name="nameType"> <xsd:restriction base="xsd:string"> <xsd:maxLength value="32" fixed="true"/> </xsd:restriction> </xsd:simpleType>