The schemas that we have written up to this point have had no target namespace declaration. We also could only describe elements and attributes that didn’t belong to any namespace.
The declaration of a target namespace gives us the possibility of defining elements and attributes that belong to the target namespace (called “qualified”) and elements and attributes that don’t belong to any namespace (called “unqualified”).
The purpose of a schema is to describe a vocabulary, in which top-level nodes belong to its target namespace. For this reason, it is forbidden to define global elements that are unqualified when a target namespace is declared.
The distinction between qualified and unqualified elements and
attributes is made through their <form>
attributes—for example:
<xs:element name="book" form="qualified"/> <xs:attribute name="isbn" form="qualified"/> <xs:attribute name="lang" form="unqualified"/> <xs:element name="character" form="unqualified"/>
The default values of these form
attributes are
defined in the elementFormDefault
and
attributeFormDefault
attributes that we have added in our
xs:schema
element.
These attributes both have default values of their own, which are:
elementFormDefault="unqualified"
and
attributeFormDefault="unqualified"
. These values
are appropriate to the case in which only the document element uses a
namespace:
<lib:library xmlns:lib="http://dyomedea.com/ns/library"> <book id="b0836217462" available="yes"> <isbn> 0836217462 </isbn> <title> Being a Dog Is a Full-Time Job </title> </book> </lib:library>
Since global elements and attributes must be qualified, defining this schema as a single schema requires that all the elements and attributes are locally defined.
Another combination,
elementFormDefault="qualified"
and
attributeFormDefault="unqualified"
matches the
common case in which a namespace is attached to the root element as
the default namespace that will, by definition apply to the included
elements but not to the attributes. (Per the Namespaces
Recommendation, the default
namespace does not apply to attributes.)
<library xmlns="http://dyomedea.com/ns/library"> <book id="b0836217462" available="yes"> <isbn> 0836217462 </isbn> <title> Being a Dog Is a Full-Time Job </title> </book> </library>
The usage considers that unqualified attributes belong to the same
vocabulary as their
parent element, and the vocabularies that take advantage of qualified
attributes are often vocabularies that supply attributes used in
elements from other namespaces. Examples of such vocabularies include
RDF and attribute-only vocabularies such as XLink and XML Base. The
schemas for these vocabularies will benefit from an
attributeFormDefault
set to qualified.
One should pay attention to the special status of the attributes in the namespace specification. The default namespace does not apply to attributes. This means that an attribute without a prefix is considered to have no namespace.
Another confusing aspect of attributes with a prefix (which thus belong to a namespace) is these attributes are called "global attributes” in the namespaces recommendation. In W3C XML Schema the term global is used differently, in opposition to local elements or attributes. A global attribute, per namespaces, is therefore a qualified attribute per W3C XML Schema, and may be globally or locally defined.
Remember that <elementFormDefault>
and
<attributeFormDefault>
define default values
and that you can specify—element by element and attribute by
attribute—if they are qualified or not.
Before we see how we can bring more namespaces into the game, let’s look at a simple instance document with a single namespace and unqualified attributes:
<?xml version="1.0"?> <library xmlns="http://dyomedea.com/ns/library"> <book id="b0836217462" available="yes"> <isbn> 0836217462 </isbn> <title> Being a Dog Is a Full-Time Job </title> <authors> <person id="CMS"> <name> Charles M Schulz </name> <born> 1922-11-26 </born> <dead> 2000-02-12 </dead> </person> </authors> <characters> <person id="PP"> <name> Peppermint Patty </name> <born> 1966-08-22 </born> <qualification> bold, brash and tomboyish </qualification> </person> <person id="Snoopy"> <name> Snoopy </name> <born> 1950-10-04 </born> <qualification> extroverted beagle </qualification> </person> <person id="Schroeder"> <name> Schroeder </name> <born> 1951-05-30 </born> <qualification> brought classical music to the Peanuts strip </qualification> </person> <person id="Lucy"> <name> Lucy </name> <born> 1952-03-03 </born> <qualification> bossy, crabby and selfish </qualification> </person> </characters> </book> </library>
If we want to avoid confusion while writing a schema for this instance document, we can define prefixes in the schema for both our target namespace and for the W3C XML Schema namespace, leading to a schema such as:
<?xml version="1.0"?> <xs:schema targetNamespace="http://dyomedea.com/ns/library" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:lib="http://dyomedea.com/ns/library" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element name="book" type="lib:bookType"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="born" type="xs:date"/> <xs:element name="dead" type="xs:date" minOccurs="0"/> <xs:element name="qualification" type="xs:string" minOccurs="0"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="required"/> </xs:complexType> </xs:element> <xs:complexType name="bookType"> <xs:sequence> <xs:element name="isbn" type="xs:NMTOKEN"/> <xs:element name="title" type="xs:string"/> <xs:element name="authors"> <xs:complexType> <xs:sequence> <xs:element ref="lib:person" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="characters"> <xs:complexType> <xs:sequence> <xs:element ref="lib:person" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="available" type="xs:string" use="required"/> </xs:complexType> </xs:schema>
In this example, the names of components defined by the schema are
always unprefixed when they are defined. Because this schema only
defines components in the single http://dyomedea.com/ns/library namespace
(identified as the targetNamespace
attribute of
the xs:schema
element), there isn’t any risk of
confusion. The only other namespaces used here are the namespace for
W3C XML Schema itself, identified with an xs
prefix, and another mapping for the http://dyomedea.com/ns/library namespace,
using lib
as the prefix. The
lib
-prefixed form is used for cross-references
between declarations.
A strictly equivalent schema, defining the exact same data model, can be defined using the target namespace as the default namespace of the schema document:
<?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="http://dyomedea.com/ns/library"> <xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element name="book" type="bookType"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="born" type="xs:date"/> <xs:element name="dead" type="xs:date" minOccurs="0"/> <xs:element name="qualification" type="xs:string" minOccurs="0"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="required"/> </xs:complexType> </xs:element> <xs:complexType name="bookType"> <xs:sequence> <xs:element name="isbn" type="xs:NMTOKEN"/> <xs:element name="title" type="xs:string"/> <xs:element name="authors"> <xs:complexType> <xs:sequence> <xs:element ref="person" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="characters"> <xs:complexType> <xs:sequence> <xs:element ref="person" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="available" type="xs:string" use="required"/> </xs:complexType> </xs:schema>
In this version, all references to W3C XML Schema’s
own elements are still made using the xs
prefix.
Names of components are still unprefixed, but the
lib
prefix is now unnecessary, so all of those
prefixes can disappear. Because the default namespace is defined in
this document, W3C XML Schema will understand the connection between
the components it defines and references to those components.
If you prefer to use prefixes on the components you are defining and
use the W3C XML Schema vocabulary without prefixes, you can also
define the W3C XML Namespace as the default namespace and declare a
prefixed namespace (here, lib
) for the components
you’re
defining:
<?xml version="1.0"?> <schema targetNamespace="http://dyomedea.com/ns/library" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:lib="http://dyomedea.com/ns/library"> <element name="library"> <complexType> <sequence> <element name="book" type="lib:bookType"/> </sequence> </complexType> </element> <element name="person"> <complexType> <sequence> <element name="name" type="string"/> <element name="born" type="date"/> <element name="dead" type="date" minOccurs="0"/> <element name="qualification" type="string" minOccurs="0"/> </sequence> <attribute name="id" type="ID" use="required"/> </complexType> </element> <complexType name="bookType"> <sequence> <element name="isbn" type="NMTOKEN"/> <element name="title" type="string"/> <element name="authors"> <complexType> <sequence> <element ref="lib:person" maxOccurs="unbounded"/> </sequence> </complexType> </element> <element name="characters"> <complexType> <sequence> <element ref="lib:person" maxOccurs="unbounded"/> </sequence> </complexType> </element> </sequence> <attribute name="id" type="ID" use="required"/> <attribute name="available" type="string" use="required"/> </complexType> </schema>
The references to W3C XML Schema data types are now done without a prefix while the references to components defined in the target namespace are done with a “lib” prefix.