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‑). 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‑)
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‑), 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=""><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">
<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">
<m:b> <m:c>ghi</m:c> </m:b> <d> 35 <m:e>jkl</m:e> </d> </a> </tree> </trees-with-namespaces>
|
Long hand definition of namespaces in each element |
|
Use of inheritance for the |
|
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‑
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‑) 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.