Friday, July 07, 2006

A Short Explanation of XML Namespaces

I wrote this up in response to a question on the Axis User discussion list, but thought others might appreciate it.

The purpose of a namespace qualification is to disambiguate two
components of the same name. For example, if you have multiple schemas
that each defines an element called "foo", how do you tell them apart?

<s:schema
xmlns:s="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:example:foo:1">
<s:element name="foo" type=s:string"/>
</s:schema>

<s:schema
xmlns:s="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:example:foo:2">
<s:element name="foo" type=s:int"/>
</s:schema>

<s:schema s="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="urn:example:foo:1"
xmlns:ns2="urn:example:foo:2"
targetNamespace="urn:example:foo:0">
<s:import namespace="urn:example:foo:1"/>
<s:import namespace="urn:example:foo:2"/>
<s:element name="foo">
<s:complexType>
<s:sequence>
<s:element ref="ns1:foo"/>
<s:element ref="ns2:foo"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>


An instance document of this element could look like this:

<ns0:foo
xmlns:ns0="urn:example:foo:0"
xmlns:ns1="urn:example:foo:1"
xmlns:ns2="urn:example:foo:2">
<ns1:foo>some string</ns1:foo>
<ns2:foo>12345</ns2:foo>
</ns0:foo>


This instance is equally valid (but less readable):

<tns:foo xmlns:tns="urn:example:foo:0">
<tns:foo xmlns:tns="urn:example:foo:1">
some string</tns:foo>
<tns:foo xmlns:tns="urn:example:foo:2">
12345</tns:foo>
</tns:foo>


In other words, the string used for the prefix is irrelevant -- what
matters is the namespace it's been assigned to and the scope of the
namespace declaration. A namespace declaration applies to the element
it's defined in and all that element's children, but you can always
reassign the prefix to a different namespace in a child element.

The default namespace declaration (e.g., xmlns="urn:example:foo:0")
says that all non-explicitly qualified elements belong to the default
namespace. I generally recommend avoiding use of the default namespace
-- especially if you have unqualified elements -- because that forces
you to override the default namespace (e.g., xmlns="") on all
unqualified elements.

So for example, let's say I have this schema:

<s:schema
xmlns:s="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:example:foobar">
<s:element name="foobar">
<s:complexType>
<s:sequence>
<s:element name="foo" type="s:string"/>
<s:element name="bar" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>


Because the schema does not specify elementFormDefault="qualified",
all local elements ("foo" and "bar") are unqualified. A valid instance
of this schema is:

<tns:foobar xmlns:tns="urn:example:foobar">
<foo>some string</foo>
<bar>another string</bar>
</tns:foobar>


But the following instance is not valid because "foo" and "bar" must be unqualified:

<foobar xmlns="urn:example:foobar">
<foo>some string</foo>
<bar>another string</bar>
</foobar>


This instance is valid:

<foobar xmlns="urn:example:foobar">
<foo xmlns="">some string</foo>
<bar xmlns="">another string</bar>
</foobar>

11 comments:

Aj said...

This is one of the most useful explanations for a newbie and I've seen similar questions asked over and over in the mailing lists. Thanks Anne for the wonderful job in writing this up.

Marc de Graauw said...

Anne, you write: "I generally recommend avoiding use of the default namespace".

I'd agree in general, but I think the exception is the case when elements are qualified (as opposed to your example) and all (or most) of the names belong to a single namespace. In this case I believe a default namespace on the document element is a good practice which yields clear and readable instances.

Shmuel Koller said...

I think the this explanation should be extended to explain the term "targetNamespace". Making this extra explanation here will make thinks more self contained.

Its clear the namespaces as explained are mostly "external" to current XML and referred-to for uniqueness/unambiguity.

Anne Thomas Manes said...

The targetNamespace attribute (which is used in definition documents, such as schema and WSDL files) essentially creates a namespace, and it indicates that elements, types, and other entities defined in the definition document belong to the namespace.

hetal said...

how can i fix namespace like ns0

Anne Thomas Manes said...

Hetal -- I don't understand your question. What's wrong with ns0? Or are you trying to permanently assign the prefix?

hetal said...

using xml schema file i am adding the placeholders in wordml file
then if i see in nodepade this wordml file it save namespace ns1 or ns2 or sometime ns0
i want to fix with ns0 only
how can i do ,if you provide me email address then i can send you xml schema file as well

hetal said...

anne- how can i assing fix value to prefix

Anne Thomas Manes said...

Hetal -- please send me email at atmanes AT gmail DOT com.

Anne Thomas Manes said...

As far as I am aware, there is no way to permanently assign a namespace prefix. You could process an instance document using XSLT or Schematron and transform it so that the prefix assigned to a specific namespace is always "ns0". But as I said in the original post, the string value used for the prefix is not significant, and you should not require use of a specific prefix string in an instance document.

abby brock said...

My partner and I stumbled over here from a different web page and thought I might check things out. I like what I see so now i am following you. Look forward to going over your web page repeatedly.

movers in virginia