By Peter Bell

XSD: Namespaces

So, to (hopefully) round out my series on Schemas, here is a short posting on namespaces . . .

Here is an example from the spec. Part of the XSD:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">


<element name="purchaseOrder" type="po:PurchaseOrderType"/>
<element name="comment" type="string"/>

<complexType name="PurchaseOrderType">
<sequence>
<element name="shipTo" type="po:USAddress"/>
<element name="billTo" type="po:USAddress"/>
<element ref="po:comment" minOccurs="0"/>
<!-- etc. -->
</sequence>
<!-- etc. -->
</complexType>

<complexType name="USAddress">
<sequence>
<element name="name" type="string"/>
<element name="street" type="string"/>
<!-- etc. -->
</sequence>
</complexType>

<!-- etc. -->
</schema>

And an associated instance document:

<?xml version="1.0"?>
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
orderDate="1999-10-20">

<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<!-- etc. -->
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<!-- etc. -->
</billTo>
<apo:comment>Hurry, my lawn is going wild<!/apo:comment>
<!-- etc. -->
</apo:purchaseOrder>

The spec states:

The instance document declares one namespace, http://www.example.com/PO1, and associates it with the prefix apo:. This prefix is used to qualify two elements in the document, namely purchaseOrder and comment. The namespace is the same as the target namespace of the schema in po1.xsd, and so a processor of the instance document will know to look in that schema for the declarations of purchaseOrder and comment. In fact, target namespaces are so named because of the sense in which there exists a target namespace for the elements purchaseOrder and comment. Target namespaces in the schema therefore control the validation of corresponding namespaces in the instance.

The prefix apo: is applied to the global elements purchaseOrder and comment elements. Furthermore, elementFormDefault and attributeFormDefault require that the prefix is not applied to any of the locally declared elements such as shipTo, billTo, name and street, and it is not applied to any of the attributes (which were all declared locally). The purchaseOrder and comment are global elements because they are declared in the context of the schema as a whole rather than within the context of a particular type. For example, the declaration of purchaseOrder appears as a child of the schema element in po1.xsd, whereas the declaration of shipTo appears as a child of the complexType element that defines PurchaseOrderType.

When local elements and attributes are not required to be qualified, an instance author may require more or less knowledge about the details of the schema to create schema valid instance documents. More specifically, if the author can be sure that only the root element (such as purchaseOrder) is global, then it is a simple matter to qualify only the root element. Alternatively, the author may know that all the elements are declared globally, and so all the elements in the instance document can be prefixed, perhaps taking advantage of a default namespace declaration. (We examine this approach in Global vs. Local Declarations (ยง3.3).) On the other hand, if there is no uniform pattern of global and local declarations, the author will need detailed knowledge of the schema to correctly prefix global elements and attributes.

Let's look a little more carefully at what is going on here. In the Schema there are two namespaces, defined: xmlns="http://www.w3.org/2001/XMLSchema" xmlns:po="http://www.example.com/PO1"

So, the default namespace (for any tags in the schema not prefixed with a namespace) is the standard XML Schema namespace. The po namespace is the custom namespace which is referring to this xsd. So, as we go down the Schema, elements like "element" and "attribute" refer the the definitions in http://www.w3.org/2001/XMLSchema, but elements prefixed with a "po" like po:USAddress refer to definitions within http://www.example.com/PO1.

How does it know that http://www.example.com/PO1 is the namespace for this xsd? Because the targetNamespace for the xsd is set to the same URI with the targetNamespace="http://www.example.com/PO1".

What about the instance document?

Well, the schema was set up with unqualified locals for elements and attributes (elementFormDefault="unqualified" attributeFormDefault="unqualified"). This is actually the default status, so you don't need to declare these if they are unqualified. What they mean is that only globally defined elements/attributes need to be prefixed with a namespace which is why in the instance document above that only purchaseOrder and comment are prefixed with apo:.

Of course, the problem with this is that now to create an instance document you have to know what elements were defined globally and what ones were local.

A Reference to a Schema
Notice that the above instance document referenced a schema in it's root purchaseOrder element with a xmlns:apo="http://www.example.com/PO1" statement. You can even go a little further by adding the following three statements: xmlns="http://www.w3schools.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com/note.xsd" which allows it to fully reference the schema and its location (from a good online tutorial).

So, it seems to me like the following would be a reasonably well formed schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.test.com/client/product"
xmlns="http://www.test.com/client/product"
elementFormDefault="qualified">

<xs:element name="product">
<xs:complexType>
<xs:sequence>
. . .
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

It sets up the schema as XML version 1.0 with UTF-8 encoding, states that the xs namespace refers to http://www.w3.org/2001/XMLSchema, that this schema is related to the http://www.test.com/client/product URI, and that the same URI is the default namespace (so elements from that namespace don't need to be prefixed). Finally it states that elements must be qualified (although not attributes) which seems to be a common approach.

Thoughts?

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.005.