XML Namespaces Primer
Why do we need namespaces?
Namespaces provide a way to:
- Distinguish between two different types of elements in an XML document that share the same name.
- Group common elements together.
What Do Namespace Names Point At?
One of the confusing aspects is that, by convention, namespace names are URLs. You might expect that since they are web addresses, they must point to something special. They do not. A namespace name may be a URL, but it is immaterial what they point to; it is only important that the namespace name is unique. The reason that URLs are used as namespace names is that they contain domain names (e.g., www.dataaccess.com), which are globally unique across the Internet.
In an XML document, the namespace URL is associated with a prefix. The prefix is used with each element to indicate which namespace the element belongs to. For example, the part before the colon is the prefix, and the part after the colon is the local part. Any prefixed element is called a qualified name, while any un-prefixed element is an unqualified name.
Namespaces by Example
The XML document below contains a node with several child nodes. Imagine this data refers to airline reservations.
<reservations>
<reservation>
<from>Chicago</from>
<to>Phoenix</to>
<id>d4</id>
<passenger>Jim Shoe</passenger>
<date>06/05/05</date>
</reservation>
<reservation>
<from>Boston</from>
<to>Miami</to>
<id>c1</id>
<passenger>Bob Sled</passenger>
<date>06/05/05</date>
</reservation>
</reservations>
If this were the only XML document with reservations we needed to process, then namespaces would be unnecessary. However, what if we also needed to process rental car reservations as shown in the following XML document?
<rentalReservations>
<car>
<model>Chevrolet Cavalier</model>
<from>Chicago</from>
<to>Phoenix</to>
<driver>Jim Shoe</driver>
<date>06/06/05</date>
</car>
<car>
<model>Dodge Caravan</model>
<from>Miami</from>
<to>Chicago</to>
<driver>Bob Sled</driver>
<date>06/06/05</date>
</car>
</rentalReservations>
This document also contains <from> and <to> tags, but the data stored in the elements differs from that in the airline reservation document. What happens if we need to combine both XML documents and process the resulting combined XML?
In this case, we will need some way to distinguish air travel reservations from rental car reservations. We can do this by using prefixes as shown in the combined XML document below:
<combinedReservations xmlns:air="www.dataaccess.com/airTravel" xmlns:car="www.dataaccess.com/carTravel">
<air:reservations>
<air:reservation>
<air:from>Chicago</air:from>
<air:to>Phoenix</air:to>
<air:id>d4</air:id>
<air:passenger>Jim Shoe</air:passenger>
<air:date>06/05/05</air:date>
</air:reservation>
<air:reservation>
<air:from>Boston</air:from>
<air:to>Miami</air:to>
<air:id>c1</air:id>
<air:passenger>Bob Sled</air:passenger>
<air:date>06/05/05</air:date>
</air:reservation>
</air:reservations>
<car:rentalReservations>
<car:car>
<car:model>Chevrolet Cavalier</car:model>
<car:from>Chicago</car:from>
<car:to>Phoenix</car:to>
<car:driver>Jim Shoe</car:driver>
<car:date>06/06/05</car:date>
</car:car>
<car:car>
<car:model>Dodge Caravan</car:model>
<car:from>Miami</car:from>
<car:to>Chicago</car:to>
<car:driver>Bob Sled</car:driver>
<car:date>06/06/05</car:date>
</car:car>
</car:rentalReservations>
</combinedReservations>
Prefixes have no meaning by themselves. The above example is not valid because the prefixes are not associated with a namespace. A namespace and its prefix are defined with the xmlns attribute (e.g., xmlns:namespacePrefix="namespaceName").
Note that it is the namespace name that must be unique. The namespace name often references some domain belonging to the organization that controls the structure of the XML data grouped under that namespace. In such a case, the namespace will look like a URL, but it is not. It merely uses a URL-like name to create a unique namespace. The URL does not have to exist.
Another way to combine the air and car reservations in a single XML document might be as follows:
<combinedReservations xmlns:car="www.dataaccess.com/carTravel" xmlns:tp="www.dataaccess.com/travel">
<air:reservations>
<air:reservation>
<air:from>Chicago</air:from>
<air:to>Phoenix</air:to>
<air:id>d4</air:id>
<air:passenger>Jim Shoe</air:passenger>
<air:date>06/05/05</air:date>
</air:reservation>
<air:reservation>
<air:from>Boston</air:from>
<air:to>Miami</air:to>
<air:id>c1</air:id>
<air:passenger>Bob Sled</air:passenger>
<air:date>06/05/05</air:date>
</air:reservation>
</air:reservations>
<car:rentalReservations>
<car:car>
<car:model>Chevrolet Cavalier</car:model>
<car:from>Chicago</car:from>
<car:to>Phoenix</car:to>
<car:driver>Jim Shoe</car:driver>
<car:date>06/06/05</car:date>
</car:car>
<car:car>
<car:model>Dodge Caravan</car:model>
<car:from>Miami</car:from>
<car:to>Chicago</car:to>
<car:driver>Bob Sled</car:driver>
<car:date>06/06/05</car:date>
</car:car>
</car:rentalReservations>
</combinedReservations>
In this document, we can still distinguish between air and car reservations because each element has a prefix that points to a different namespace. In this example, we also created yet another namespace and prefix for the entire document.
Default Namespace
Defining a default namespace for an element means we don't have to use prefixes in the child elements. A default namespace definition has the following syntax:
xmlns="namespace"
For example:
<items xmlns="www.dataaccess.com/items">
<item>Art Deco Chrome Frame</item>
<item>190</item>
</items>
In this example, the <item> elements all belong to the defined namespace without the need to use a prefix.
The following document is identical to the earlier example:
<items xmlns="www.dataaccess.com/items">
<item>Chicago</item>
<item>Phoenix</item>
<item>d4</item>
<item>Jim Shoe</item>
<item>06/05/05</item>
<item>Boston</item>
<item>Miami</item>
<item>c1</item>
<item>Bob Sled</item>
<item>06/05/05</item>
<item>Chevrolet Cavalier</item>
<item>Chicago</item>
<item>Phoenix</item>
<item>Jim Shoe</item>
<item>06/06/05</item>
<item>Dodge Caravan</item>
<item>Miami</item>
<item>Chicago</item>
<item>Bob Sled</item>
<item>06/06/05</item>
</items>
The default namespace only applies to document elements. Attributes either belong to a specific namespace (as defined by a prefix before the attribute name) or, if there is no prefix, they belong to the global namespace.
Global Namespace
When an XML document does not define any namespace (using the xmlns attribute), then each element and attribute of that document can be said to belong to the global namespace, i.e., the namespace shared by all elements and attributes of all XML documents where namespaces are not defined.
Processing XML Documents with Namespaces in DataFlex
When writing DataFlex code to process XML documents that use namespaces, you should use the namespace-aware methods defined for the cXMLDOMDocument class.
For more information, refer to the section titled "Processing XML Documents with Namespaces" in the cXMLDOMDocument class documentation.