2.1. Namespaces

Until now we wrote XML element name as a simple identifier, but in fact the full name of an element (or an attribute) is an identifier combined with a namespace which is an arbitrary string. If the string is empty, then we consider that the element is in the empty namespace. But usually a namespace is a long string that we would like to be unique for an individual or a corporation. One convenient way of ensuring unique name is to use strings that are similar to urls; the reasons for this will be explained in Chapter 7, but for the moment we will use short strings to simplify the explanations.

The namespace for an element is specified using the xmlns as illustrated in the first tree in Example 2.4 (line 7‑1). Elements named b, c and e are in the mary namespace, while a and d are in the john namespace.

When the xmlns attribute is not specified for an element, it is looked up in the ancestors of the node (first the parent, then parent of the parent and so on). The first value associated with an xmlns attribute encountered is assigned to the current element. If no xmlns attribute is encountered then the current element is considered to be in the empty namespace (equivalent to the declaration of xmlns=""). The second tree (line 18‑2) shows how the namespaces for elements tree, c and d are inherited by this rule to give equivalent element names as the ones in the first tree.

But using xmlns can become burdensome and error-prone, so the usual way of specifying namespaces is by declaring a prefix, usually only a few letters long, for a given namespace and then using the prefix in front of the element names. The prefix is specified with xmlns:prefix=string which defines the prefix as specifying the namespace for the entire subtree of the element, including itself. In the third tree (line 30‑3), in element a, m is declared as a prefix for denoting the mary namespace, which is then used for elements b, c and e. The prefix string has no significance in itself outside of referencing the full string of the namespace. Different prefixes could in principle be used in different parts of the same XML file for referencing the same namespace although this would be less convenient for a human reader. When most of the elements of an XML tree are to be put in a given namespace, it is often advantageous to declare the namespace as the default namespace in the root element tag, so that all elements in the tree without a prefix will be automatically put in the given namespace.

Example 2.4. [NamespaceExample.xml] A simplistic example of declaration and use of namespaces

Three equal XML trees showing different ways of assigning namespaces to elements. The convention used in the third tree is most often used.

  1 <?xml version="1.0" encoding="UTF-8"?>
    <!-- simple illustration of the definition of namespaces: 
         all three tree elements are equal -->
    <trees-with-namespaces>
  5     <!-- Names of namespaces are short here for simplicity, 
             but they should be unique long strings... -->
        <tree no="1" xmlns="">                                           (1)
            <a xmlns="john">
                <b xmlns="mary">
 10                 <c xmlns="mary">ghi</c>
                </b>
                <d xmlns="john">
                    <e xmlns="mary">jkl</e>
                </d>
 15         </a>
        </tree>
        <!-- xmlns declaration are inherited from the ancestors -->
        <tree no="2">                                                    (2)
            <a xmlns="john">
 20             <b xmlns="mary">
                    <c>ghi</c>
                </b>
                <d>
                    <e xmlns="mary">jkl</e>
 25             </d>
            </a>
        </tree>
        <!-- prefix declarations span the tree and simplify notation -->
        <tree no="3">
 30         <a xmlns="john" xmlns:m="mary">                              (3)
                <m:b>
                    <m:c>ghi</m:c>
                </m:b>
                <d>
 35                 <m:e>jkl</m:e>
                </d>
            </a>
        </tree>
    </trees-with-namespaces>

1

Long hand definition of namespaces in each element

2

Use of inheritance for the xmlns attribute.

3

Definition of a prefix for the elements that are not in the same namespace as the one of the parent.


Namespaces allow a graceful combination of independent XML files. Coming back to our running example (Example 2.1), let us see how these principles are used in a larger and less artificial context: Example 2.2 includes Example 2.3 via the element xi:include. These files both use the wine element, but in different ways: in Example 2.3, wine refers to a description of a wine type while in Example 2.2 wine refers to a batch of bottles. Both references must be distinguished from one another in order to validate them with the appropriate XML Schema. In such a simple case, it would be an easy matter, and probably a better design, to have different names for these two concepts but we want to illustrate the use of namespaces in a small scale example. A similar name clash could happen if we wanted to combine independently created XML files.

For example, in the root tag of line 6‑4 of Example 2.2, two namespace prefixes are defined: xsi and cat, for which are given two arbitrary unique identifiers that will be used to distinguish their namespaces. Most often, identifiers of namespaces are URLs (URIs more precisely) because the authors of an XML file use a URL linking to a web site they own. If authors take care not to use the same URL for different purposes, this pretty much guarantees the uniqueness of the namespaces. This does not necessarily means that the URLs used as names for namespaces do exist. It must be stressed that the URL notation is nothing more than a useful convention, although this name can also be used by validators as a hint to find the corresponding schema.

By default, names without prefixes are defined in the empty namespace or in the value assigned to the xmlns attribute. To create elements in a specific namespace, we assign a default namespace like we did at the start of Example 2.3 by specifying a value for the xmlns attribute (line 4). In principle, any element can set a value for the xmlns attribute to change the default namespace or to set the prefix of new namespaces for nested elements. As namespace prefixes are inherited, the search for the URI corresponding to a prefix starts from the current element and follows the parent links in the tree until it finds a corresponding prefix declared as a value of a xmlns attribute.

As shown in Example 2.1, the declaration of namespaces is most often done at the root element of the file. In this listing, elements in italics are in a different namespace. A non-italicized element must use a prefix to refer to an element in italics. Within italicized code, no prefix is necessary because the namespace has been given a null prefix (line 4) within the box. It is possible to define a namespace for any element (which will also apply to its subelements) but this makes it hard for the human reader to be aware of the current namespace of an element. However, a namespace aware XML processor has no problem because a namespace is associated with each element. For example, in Example 2.2, cat:bold designates the bold element in the http://www.iro.umontreal.ca/lapalme/wine-catalog namespace. All elements in the Example 2.3 also have the same namespace; so bold elements (line 20‑5) are the same: i.e. when, as will be explained later, they will be processed by an XML system, they will be identified as being of the same type.

The use of namespaces will be better understood once we have seen their use in validation with schemas (Section 3.2.3). An excellent short introduction to the concept of namespace can be found in [59], pp. 160—166. Namespaces are fundamental in the context of the semantic web as discussed in Chapter 7.