XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Namespace Nuances

Namespace Nuances

July 05, 2001

Q: I can't validate a document using namespaces, can I?

I'm trying to validate an XML file. It uses XML namespaces, but I can't figure out how to express them inside the DTD. Here's a sample XML document:

<?xml version="1.0"?>
<!DOCTYPE checkbook SYSTEM "checkbook.dtd">
<checkbook xmlns:f="http://schemas.ar-ent.net/soap/file/"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:m="http://schemas.ar-ent.net/test/soap.tr/checkbook/"
xmlns:ars="http://schemas.ar-ent.net/soap/">
<f:deposit type="direct-deposit">
<payor>Bob's Bolts</payor>
<amount>987.32</amount>
<date>21-6-00</date>
<description category="income">Paycheck</description>
</f:deposit>
</checkbook>

And here's a portion of the DTD, covering the markup included above,

<!ELEMENT checkbook (deposit|payment)*>
<!ELEMENT deposit (payor, amount, date, description?)>
<!ATTLIST deposit
type (cash|check|direct-deposit|transfer) #REQUIRED>
<!ELEMENT amount (#PCDATA)>
<!ELEMENT date (#PCDATA)>
<!ELEMENT payor (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ATTLIST description
category (cash|entertainment|food|income|work) 'food'>

And this is error message I'm getting:

Unknown element 'f:deposit'

A: I can see why you're frustrated. It certainly appears as though you've got everything accounted for in your document, with all those namespace declarations.

To help resolve your problem, let's review the basics of namespaces and their declarations, covering only what you need to know to deal with this particular problem. (A terrific resource for all kinds of questions about namespaces is Ron Bourret's XML Namespaces FAQ.)

Why namespaces?

Namespaces enable you to mix, in one XML document, element (and sometimes attribute) names from more than one XML vocabulary. Let's assume you've got a document in some vocabulary which looks, in part, like the following:

<furniture>
<table material="mahogany" type="dining"/>
<chair material="mahogany" type="dining"/>
<chair material="mahogany" type="dining"/>
<lamp material="brass" type="chandelier"/>
</furniture>

You show this to your boss at the furniture warehouse. He's not exactly the brightest bulb in the lamp, but he is your boss, and he says, "Well, that's okay. But I really want you to enclose all those individual types of furniture in a table."

"A table?" you ask.

"Sure. Like in a Web page. Rows and columns. A table."

What he's looking for, in short, would be something like this:

<furniture>
<table>
<tr>
<td><table material="mahogany" type="dining"/></td>
<td><chair material="mahogany" type="dining"/></td>
<td><chair material="mahogany" type="dining"/></td>
<td><lamp material="brass" type="chandelier"/></td>
</tr>
</table>
</furniture>

See the problem? You've got two element types, representing two different things, both called table. You need to disambiguate the names -- that is, make it clear which kind of table element you're referring to at any point in the document.

Declaring a Namespace

Also in XML Q&A

From English to Dutch?

Trickledown Namespaces?

From XML to SMIL

From One String to Many

Getting in Touch with XML Contacts

To declare a namespace is to declare which vocabulary an element name comes from. The specific device for doing so is a special attribute, xmlns, which can be placed on any element in a document. This attribute takes the form:
xmlns:prefix="namespaceURI"
This is what we refer to when we speak of a "namespace declaration." As for the pieces of the declaration:

  • xmlns is required; it identifies this as an XML namespace declaration.
  • :prefix (note the leading colon) is optional. If you include it, all element names in the document from the indicated namespace (vocabulary) must be prefixed with these characters, followed by a colon. (We'll see examples in a moment.)
  • namespaceURI is required. It uniquely identifies a namespace in this document and perhaps in others. The term "URI" here is a little misleading; although it looks like a familiar Web URI, it needn't actually "point to" anything in particular. Even many of the standard W3C namespace URIs don't locate a document, like a DTD, which formally describes the vocabulary. The important feature of the namespace URI is that it be unique among all namespace URIs in the document.

For the furniture example above, you could do something like the following (changes in boldface):

<furn:furniture xmlns:furn="http://myfurn/namespace"
xmlns="http://www.w3.org/1999/xhtml"
>
<table>
<tr>
<td><furn:table material="mahogany" type="dining"/></td>
<td><furn:chair material="mahogany" type="dining"/></td>
<td><furn:chair material="mahogany" type="dining"/></td>
<td><furn:lamp material="brass" type="chandelier"/></td>
</tr>
</table>
</furn:furniture>

Now the furniture element and all its descendants will "know about" the furn namespace prefix. (Namespaces, like special attributes such as xml:lang, are in effect for the scope of whatever element declares them, unless redefined by some descendant.) The second namespace declaration asserts that all unprefixed element names in the document also come from a particular namespace (XHTML 1.0, in this case). Consequently, any namespace-aware application which processes this document will recognize two distinct types of table element in this document: one from the furniture-related vocabulary and one from XHTML 1.0.

Pages: 1, 2

Next Pagearrow