- Why Namespaces Are Needed: Resolving Name Conflicts
- Qualified Names, Prefixes, Local Names, and Other Terminology
- Declaring Namespaces in XML Documents
- Default Namespace
- Handling Namespaces in a DTD or XML Schema
- Validating Documents with Namespaces
- What Does a Namespace Point To?
- Namespace Support and Use
- Special Attributes: xmlns, xml:space, xml:lang, and xml:base
- Common Namespaces
- Summary
- For Further Exploration
Declaring Namespaces in XML Documents
In an XML document, a namespace is always declared in the start tag of an element. Which element you choose to attach the namespace to determines the scope of the declaration. A namespace declaration involves a special attribute called xmlns, followed by a colon, a somewhat arbitrary prefix, and the associated URI. This special xmlns attribute can be attached to any element (and is not itself something you declare). The syntax is:
xmlns:somePrefix="someURI"
Like all attributes, it must appear in the start tag of its associated element. (Technically, xmlns is a namespace declaration that looks like an attribute with a URI as its value.) For example, here's how to declare the XLink namespace for an element called Timeline:
<Timeline xmlns:xlink="http://www.w3.org/1999/xlink" ...>
Similarly, this namespace declaration pertains to the catalog example earlier in this chapter:
<Disc:DiscountCatalog xmlns:Disc="http://www.HouseOfDiscounts.com/namespaces/Discounts" ...>
The main difference between these two namespace declarations is that for the Timeline element, we're declaring that it will be using attributes from the XLink namespace, although Timeline itself is not defined in XLink. In the case of DiscountCatalog, we are declaring a namespace whose prefix is Disc and DiscountCatalog is an element from the language. That's why the DiscountCatalog element itself needs a prefix. Now, if it strikes you as slightly strange that in this second example we're using the prefix a nanosecond before we've actually declared it, then that gives you an idea of one of the headaches that parser developers have to consider (you didn't really want to write your own parser, did you?). This is the correct way to declare the namespace in this case, however.
The scope of a namespace declaration is the element in which it is declared, plus all descendants of that element, unless a descendant explicitly overrides the namespace it inherits from its ancestors by declaring another namespace. Therefore, we can use XLink attributes with any descendant of Timeline, or on the Timeline element itself:
<Timeline xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="extended" > <Band xlink:type="locator" xlink:label="index" xlink:href="wings.html"> Wings Timeline (1971-1981) </Band> <Recording xlink:type="locator" xlink:label="wwl" xlink:href="a/wwl.html" year="1971">Wings Wild Life </Recording> <!-- etc. --> </Timeline>
If we had declared the XLink namespace in the start tag of the Band element rather than on Timeline, we could not use it with Recording (or with Timeline) without an additional namespace declaration.
Similarly, we can use elements from the namespace named http://www.House OfDiscounts.com/namespaces/Discounts by using the Disc prefix:
<Disc:DiscountCatalog xmlns:Disc="http://www.HouseOfDiscounts.com/namespaces/Discounts"> <Disc:category name="Wild Animals"> <Disc:item name="Lion"> <Disc:price type="wholesale">999.99</Disc:price> </Disc:item> <Disc:item name="Tiger"> <Disc:price type="wholesale">879.99</Disc:price> </Disc:item> <Disc:item name="Bear"> <Disc:price type="wholesale">1199.99</Disc:price> </Disc:item> </Disc:category> </Disc:DiscountCatalog>
Notice that the attributes of our DiscountCatalog language (e.g., name) do not require prefixes. That's because attributes are associated with the element whose start tag contains them. Although the prefix could be used, it is unnecessary.
For this reason, attributes are not considered to be in any particular namespace unless an explicit prefix is used. We already saw one situation where a prefix is definitely necessaryXLink, which makes attributes available to any element of any language. In this case, the prefix is needed partly to avoid potential name collision with other attributes of the elements, and also to signal an XLink processor that these elements have special linking capabilities. For example, XLink defines a type attribute whose qualified name is xlink:type, so if I require another attribute named type for my Timeline element, the name type is distinguishable from xlink:type.
If for some reason we needed to override an ancestor's namespace, we could declare another namespace at any point in the hierarchy. For example, we could also declare the SuperDuperCatalog namespace for the item whose name is "Tiger":
<Disc:DiscountCatalog xmlns:Disc="http://www.HouseOfDiscounts.com/namespaces/Discounts"> <Disc:category name="Wild Animals"> <Disc:item name="Lion"> <Disc:price type="wholesale">999.99</Disc:price> </Disc:item> <Disc:item name="Tiger" xmlns:Super="http://www.EverythingUNeed.com/2002/SuperDuperCatalog"> <Disc:price type="wholesale">879.99</Disc:price> <Super:price currency="US">859.85</Super:price> </Disc:item> <Disc:item name="Bear"> <Disc:price type="wholesale">1199.99</Disc:price> </Disc:item> </Disc:category> </Disc:DiscountCatalog>
However, since the namespace declaration associated with the Super prefix appears at this nested level, its scope is strictly limited to the Disc:item element that declares it and to its Disc:price child, but not to any other Disc:item or Disc:price in the catalog. The Disc prefix is still in scope, so we can mix Disc:price and Super:price elements as children of Disc:item. (We have not said anything about validation yet and we can only verify that this example is well-formed. The content model of Disc:item would need to be defined as ANY to permit this element from another namespace, or else we would need to explicitly name the foreign elements that are allowed as content.)
NOTE
Although you may declare namespaces at any point in your hierarchy, it is generally better to declare them on the root (document) element so that they can be applied to every child of the root. While some developers prefer to push namespace declarations down to the lowest level where they occur (e.g., attached to an SVG element nested deep inside an XHTML table), declaring them at a high level allows you to change or add to your hierarchy with the least namespace impact. The tradeoff is that you must use prefixes to specify fully qualified names.
Therefore, the example would be more likely to have both namespaces declared in the root element so that elements of the namespace with the Super prefix can be used anywhere (assuming the DTD or schema supported this model, or when validation is not an issue):
<Disc:DiscountCatalog xmlns:Disc="http://www.HouseOfDiscounts.com/namespaces/Discounts" xmlns:Super="http://www.EverythingUNeed.com/2002/SuperDuperCatalog"> <Disc:category name="Wild Animals"> <Disc:item name="Lion"> <Disc:price type="wholesale">999.99</Disc:price> </Disc:item> <Disc:item name="Tiger" > <Disc:price type="wholesale">879.99</Disc:price> <Super:price currency="US">859.85</Super:price> </Disc:item> <Disc:item name="Bear"> <Disc:price type="wholesale">1199.99</Disc:price> </Disc:item> </Disc:category> </Disc:DiscountCatalog>
Namespace declarations at the document element level generally applies if we are mixing W3C vocabularies in an XML document, as we'll see in the next section.