The rules are slightly different when we define an element or
attribute by reference to a component which is in a different
namespace, rather than a datatype. In that case, the name of the
referenced component is imported, and that namespace must be the
target namespace of the imported schema.
To illustrate how this works, we'll take a closer
look at two ways to create schemas described in this simple example:
<?xml version="1.0"?>
<!-- Namespace: http://dyomedea.com/ns/library -->
<library xmlns:ppl="http://dyomedea.com/ns/people"
xmlns="http://dyomedea.com/ns/library">
<book id="b0836217462">
<title>
Being a Dog Is a Full-Time Job
</title>
<authors>
<ppl:person id="CMS">
<ppl:name>
Charles M Schulz
</ppl:name>
</ppl:person>
</authors>
</book>
</library>
This document contains two namespaces. Everything except the contents
of the authors element is in the
http://dyomedea.com/ns/library namespace. The
contents of the authors element
(ppl:person and ppl:name) are
in the http://dyomedea.com/ns/people namespace.
We have two main options for representing this document using W3C XML
Schema. Both approaches start by defining a schema for the elements
in the http://dyomedea.com/ns/library namespace.
The first approach imports the schema defining the
http://dyomedea.com/ns/people namespace, and then
uses a reference to the ppl:person element to use
it inside the authors element:
<?xml version="1.0"?>
<xs:schema targetNamespace="http://dyomedea.com/ns/library"
elementFormDefault="qualified" attributeFormDefault="unqualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ppl="http://dyomedea.com/ns/people"
xmlns:lib="http://dyomedea.com/ns/library">
<xs:import namespace="http://dyomedea.com/ns/people"
schemaLocation="very-simple-2-ns-ppl.xsd"/>
<xs:element name="library">
<xs:complexType>
<xs:sequence>
<xs:element name="book" type="lib:bookType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="bookType">
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element ref="ppl:person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/>
</xs:complexType>
</xs:schema>
The second approach does the same import, but defines the
authors element as having the type
ppl:authorType rather than defining its complex
type explicitly, resulting in a shorter schema:
<?xml version="1.0"?>
<xs:schema targetNamespace="http://dyomedea.com/ns/library"
elementFormDefault="qualified" attributeFormDefault="unqualified"
xmlns:lib="http://dyomedea.com/ns/library"
xmlns:ppl="http://dyomedea.com/ns/people"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://dyomedea.com/ns/people"
schemaLocation="very-simple-2-ns-ppl.xsd"/>
<xs:element name="library">
<xs:complexType>
<xs:sequence>
<xs:element name="book" type="lib:bookType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="bookType">
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="authors" type="ppl:authorType"/>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/>
</xs:complexType>
</xs:schema>
Although the two schemas will validate the same instance documents,
the design style is quite different. Applications relying on the
schema for information about the document will see it in two very
different ways. The first approach provides a cleaner separation
between the two namespaces. The use of the reference allows the
ppl:person element to appear inside the
authors element but does nothing to mix the
authors element with the
http://dyomedea.com/ns/people namespace directly.
The second approach is briefer, but assigns a datatype in one
namespace to an element in another namespace.