RELAX NG by Eric van der Vlist will be published by O'Reilly & Associates (ISBN: 0596004214)

You are welcome to use our annotation system to give your feedback.


A ten-minute guide to XML namespaces

Let's examine the motivations behind XML Namespaces. The first motivation is to have namespaces be a replacement for the formal public identifier (FPI), an inheritance from SGML. These identifiers provide a way to identify which vocabulary, or set of names, is being used in a document. The XML/SGML way of identifying the vocabulary used in our library would be to add a public identifier to the document type declaration such as:

 <?xml version="1.0"?>
 <!DOCTYPE library PUBLIC "-//ERICVANDERVLIST//DTD for library//EN" "library.dtd"/>
 <library>
 .../...
 </library>

This DOCTYPE declaration contains both an FPI ("-//ERICVANDERVLIST//DTD for library//EN") and the location of the DTD describing the vocabulary ("library.dtd"). XML requires that the DOCTYPE declaration always provide a SYSTEM identifier - a location - when a PUBLIC identifier is used, though PUBLIC identifiers are not required when SYSTEM identifiers are used. The creators of XML 1.0 didn't want to require parsers to include the tools (typically XML catalog processing) for resolving formal public identifiers to addresses, but kept the option open. Since the DOCTYPE declaration provides the parser with identification of the DTD rather than the identification of the abstract set of names, this approach is generally sensible.

The first goal of XML namespaces is to provide identifiers for the abstract notions of "vocabularies" and "namespaces" without linking these identifiers directly to the technical implementations (DTDs, schemas, or whatever) that define or enforce what they are. These identifiers are no longer FPIs like those used in doctype declarations but Uniform Resource Identifiers (URIs, or, to be picky, "URI references"). These identifiers can be applied to every element and attribute in a document, not just the document as a whole. To assign a namespace to all the elements from Example 3-1, we could use an xmlns attribute to assign a URI to the default namespace, writing:

 <?xml version="1.0"?>
 <library xmlns="http://eric.van-der-vlist.com/ns/library">
 .../...
 </library>

The identifier for my namespace is the string http://eric.van-der-vlist.com/ns/library. There doesn't need to be any document at this address - it's only a label. Though it looks temptingly like a hyperlink, it's not designed to be used that way. Namespaces are identifiers which give a hint about ownership. The assumption is just that I create a namespace only if I own the domain it uses and that I won't use the same identifier to identify several different things. XML namespaces per se do not define any way to associate resources such as schemas or documentations with a namespace URI. (For a mechanism that does that, see Resource Directory Description Language, at http://rddl.org.)

The namespace declaration xmlns="http://eric.van-der-vlist.com/ns/library" has been applied to the document element (library) and that declaration is inherited by all its child elements, unless the child elements provide their own namespace declarations and override it.

The second goal of XML namespaces, and the place where it goes farther than FPIs in DOCTYPE declarations, is to provide a way to mix elements and attributes from different namespaces in a single document. In our library for instance, the library and book elements use a vocabulary specific to libraries, while the author element could use a vocabulary for human resources. The character element could be a mix of both: the character element itself and the qualification element would be from the library namespace while the name and born elements would be from the HR vocabulary. Figure�1 shows shows how this might look in the XML document:

Applying the namespaces to the elements could be achieved using the 
      xmlns declaration as we have already seen:
 <?xml version="1.0"?>
 <library xmlns="http://eric.van-der-vlist.com/ns/library">
  <book id="b0836217462" available="true">
   <isbn>0836217462</isbn>
   <title xml:lang="en">Being a Dog Is a Full-Time Job</title>
   <author id="CMS" xmlns="http://eric.van-der-vlist.com/ns/person">
    <name>Charles M Schulz</name>
    <born>1922-11-26</born>
    <dead>2000-02-12</dead>
   </author>
   <character id="PP">
    <name xmlns="http://eric.van-der-vlist.com/ns/person">Peppermint Patty</name>
    <born xmlns="http://eric.van-der-vlist.com/ns/person">1966-08-22</born>
    <qualification>bold, brash and tomboyish</qualification>
    </character>
   <character id="Snoopy">
    <name xmlns="http://eric.van-der-vlist.com/ns/person">Snoopy</name>
    <born xmlns="http://eric.van-der-vlist.com/ns/person">1950-10-04</born>
    <qualification>extroverted beagle</qualification>
   </character>
   <character id="Schroeder">
    <name xmlns="http://eric.van-der-vlist.com/ns/person">Schroeder</name>
    <born xmlns="http://eric.van-der-vlist.com/ns/person">1951-05-30</born>
    <qualification>brought classical music to the Peanuts strip</qualification>
   </character>
   <character id="Lucy">
    <name xmlns="http://eric.van-der-vlist.com/ns/person">Lucy</name>
    <born xmlns="http://eric.van-der-vlist.com/ns/person">1952-03-03</born>
    <qualification>bossy, crabby and selfish</qualification>
   </character>
  </book>
 </library>

Applying namespace declarations to every element becomes very verbose very rapidly. To reduce this verbosity, XML namespaces provide a way to assign prefixes to namespaces. These prefixes can then be applied to the names of the elements (and attributes) to identify their namespaces. The namespace declared using the xmlns attribute is called the default namespace since it is assigned to elements which have no prefix. The document above could be rewritten using the default namespace for the library and by assigning an hr prefix to the other namespace:

 <?xml version="1.0"?>
 <library
   xmlns="http://eric.van-der-vlist.com/ns/library"
   xmlns:hr="http://eric.van-der-vlist.com/ns/person">
  <book id="b0836217462" available="true">
   <isbn>0836217462</isbn>
   <title xml:lang="en">Being a Dog Is a Full-Time Job</title>
   <hr:author id="CMS">
    <hr:name>Charles M Schulz</hr:name>
    <hr:born>1922-11-26</hr:born>
    <hr:dead>2000-02-12</hr:dead>
   </hr:author>
   <character id="PP">
    <hr:name>Peppermint Patty</hr:name>
    <hr:born>1966-08-22</hr:born>
    <qualification>bold, brash and tomboyish</qualification>
    </character>
   <character id="Snoopy">
    <hr:name>Snoopy</hr:name>
    <hr:born>1950-10-04</hr:born>
    <qualification>extroverted beagle</qualification>
   </character>
   <character id="Schroeder">
    <hr:name>Schroeder</hr:name>
    <hr:born>1951-05-30</hr:born>
    <qualification>brought classical music to the Peanuts strip</qualification>
   </character>
   <character id="Lucy">
    <hr:name>Lucy</hr:name>
    <hr:born>1952-03-03</hr:born>
    <qualification>bossy, crabby and selfish</qualification>
   </character>
  </book>
 </library>

If we prefer, for symmetry, we can use a prefix for both namespaces:

 <?xml version="1.0"?>
 <lib:library
   xmlns:lib="http://eric.van-der-vlist.com/ns/library"
   xmlns:hr="http://eric.van-der-vlist.com/ns/person">
  <lib:book id="b0836217462" available="true">
   <lib:isbn>0836217462</lib:isbn>
   <lib:title xml:lang="en">Being a Dog Is a Full-Time Job</lib:title>
   <hr:author id="CMS">
    <hr:name>Charles M Schulz</hr:name>
    <hr:born>1922-11-26</hr:born>
    <hr:dead>2000-02-12</hr:dead>
   </hr:author>
   <lib:character id="PP">
    <hr:name>Peppermint Patty</hr:name>
    <hr:born>1966-08-22</hr:born>
    <lib:qualification>bold, brash and tomboyish</lib:qualification>
    </lib:character>
   <lib:character id="Snoopy">
    <hr:name>Snoopy</hr:name>
    <hr:born>1950-10-04</hr:born>
    <lib:qualification>extroverted beagle</lib:qualification>
   </lib:character>
   <lib:character id="Schroeder">
    <hr:name>Schroeder</hr:name>
    <hr:born>1951-05-30</hr:born>
    <lib:qualification>brought classical music to the Peanuts strip</lib:qualification>
   </lib:character>
   <lib:character id="Lucy">
    <hr:name>Lucy</hr:name>
    <hr:born>1952-03-03</hr:born>
    <lib:qualification>bossy, crabby and selfish</lib:qualification>
   </lib:character>
  </lib:book>
 </lib:library>

Note that, for a namespace-aware application, the three previous documents are considered equivalent. The prefixes are only shortcuts to associate a namespace URI and a local name (the part of the name which is after the colon). This combination disambiguates this name from cases where the same local name is used in other namespaces.

Elements and attributes receive slightly different namespace handling. They are similar in that attribute names can be given a prefix to show that they belong to a namespace. They get special treatment in that the default namespace doesn't apply to them and any attributes which have no prefix are considered to have no namespace URI. They sort of belong to the namespace of their parent element, but not exactly. The reason for this is that attributes are supposed to be used to provide meta-data qualifying their parent element rather than to contain actual information. Being qualifiers, it is often considered that by default they belong to the same vocabulary as their parent elements. This is the reason why I have kept the id and available attributes unprefixed in my three examples.

The last goal of XML namespaces (and the motivation for taking that much effort to allow several namespaces in a single document) is to facilitate the development of independent (or semi-independent) vocabularies which can be used as building blocks. One of the ideas is that if applications are cleanly designed and just ignore elements and attributes which they don't understand, documents can be extended to support new features without breaking existing applications.

For instance, in our library we've not defined the publisher of the book. We can add a publisher element to our namespace, but instead we might want to use the definition given by the Dublin Core Metadata Initiative (DCMI). They've already created an element for representing publishers, in a namespace they've defined. We can use their namespace to write:

 <?xml version="1.0"?>
 <library
   xmlns="http://eric.van-der-vlist.com/ns/library"
   xmlns:hr="http://eric.van-der-vlist.com/ns/person"
   xmlns:dc="http://purl.org/dc/elements/1.1/">
  <book id="b0836217462" available="true">
   <isbn>0836217462</isbn>
   <title xml:lang="en">Being a Dog Is a Full-Time Job</title>
   <dc:publisher>Andrews Mc Meel Publishing</dc:publisher>
   .../...
  </book>
 </library>

There are two benefits to doing this. Firstly, everyone can easily understand that the publisher element corresponds to the definition given by the DCMI:

    URI:            http://purl.org/dc/elements/1.1/publisher
    Namespace:      http://purl.org/dc/elements/1.1/
    Name:           publisher
    Label:          Publisher
    Definition:     An entity responsible for making the resource available
    Comment:        Examples of a Publisher include a person, an organisation,
                    or a service.
                    Typically, the name of a Publisher should be used to
                    indicate the entity.
    Type of term:   http://dublincore.org/usage/documents/principles/#element
    Status:         http://dublincore.org/usage/documents/process/#recommended
    Date issued:    1998-08-06
    Date modified:  2002-10-04
    Decision:       http://dublincore.org/usage/decisions/#Decision-2002-03
    This version:   http://dublincore.org/usage/terms/dc/#publisher-004
    Replaces:       http://dublincore.org/usage/terms/dc/#publisher-003

The second benefit is that if my application has been implemented to skip elements and attributes from unsupported namespaces, the addition of this dc:publisher element won't break anything. Again, note that the mechanism to retrieve this definition is not specified by the Namespaces in XML recommendation.


You are welcome to use our annotation system to give your feedback.
[Annotations for this page]
All text is copyright Eric van der Vlist, Dyomedea. During development, I give permission for non-commercial copying for educational and review purposes. After publication, all text will be released under the Free Software Foundation GFDL.