Handling Namespaces in DTDs
Another important topic when it comes to working with DTDs is how to handle namespaces. As we already know, a namespace name is really just a name prepended to an element or attribute name with a colon. That means that as far as a DTD is concerned, those new names have to be declared.
For example, if we want to put our employees document into a namespace named emp, our elements would change from <name> to <emp:name>, from <hiredate> to <emp:hiredate>, and so on. And to make the document valid, we would have to declare those new names in the DTD.
To see how this works, you can start by declaring the namespace emp, using the attribute xmlns:emp in the document element, and then using that namespace throughout the document:
<emp:document xmlns:emp="http://www.xmlpowercorp.com/dtds/"> <emp:employee> <emp:name> <emp:lastname>Kelly</emp:lastname> <emp:firstname>Grace</emp:firstname> </emp:name> <emp:hiredate>October 15, 2005</emp:hiredate> <emp:projects> <emp:project> . . .
Now construct the DTD to match. Start with the xmlns:emp attribute itself. As you'll see tomorrow, if you use attributes in an XML document with a DTD, you have to declare them in that DTD. Here's how to do that:
<?xml version = "1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE document [ <!ELEMENT document (employee)*> <!ATTLIST document xmlns:emp CDATA #FIXED "http://www.xmlpowercorp.com/dtds/"> <!ELEMENT employee (name, hiredate, projects)> <!ELEMENT name (lastname, firstname)> <!ELEMENT lastname (#PCDATA)> <!ELEMENT firstname (#PCDATA)> <!ELEMENT hiredate (#PCDATA)> <!ELEMENT projects (project)*> <!ELEMENT project (product, id, price)> <!ELEMENT product (#PCDATA)> <!ELEMENT id (#PCDATA)> <!ELEMENT price (#PCDATA)> ]>
Now you're free to use the emp namespace when you declare each element in the DTD:
<?xml version = "1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE emp:document [ <!ELEMENT emp:document (emp:employee)*> <!ATTLIST emp:document xmlns:emp CDATA #FIXED "http://www.xmlpowercorp.com/dtds/"> <!ELEMENT emp:employee (emp:name, emp:hiredate, emp:projects)> <!ELEMENT emp:name (emp:lastname, emp:firstname)> <!ELEMENT emp:lastname (#PCDATA)> <!ELEMENT emp:firstname (#PCDATA)> <!ELEMENT emp:hiredate (#PCDATA)> <!ELEMENT emp:projects (emp:project)*> <!ELEMENT emp:project (emp:product, emp:id, emp:price)> <!ELEMENT emp:product (#PCDATA)> <!ELEMENT emp:id (#PCDATA)> <!ELEMENT emp:price (#PCDATA)> ]>
That's all there is to it. Now you can use the emp namespace throughout the document, as shown in ch04_11.xml in Listing 4.11.
Listing 4.11 Using a Namespace in an XML Document with a DTD (ch04_11.xml)
<?xml version = "1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE emp:document [ <!ELEMENT emp:document (emp:employee)*> <!ATTLIST emp:document xmlns:emp CDATA #FIXED "http://www.xmlpowercorp.com/dtds/"> <!ELEMENT emp:employee (emp:name, emp:hiredate, emp:projects)> <!ELEMENT emp:name (emp:lastname, emp:firstname)> <!ELEMENT emp:lastname (#PCDATA)> <!ELEMENT emp:firstname (#PCDATA)> <!ELEMENT emp:hiredate (#PCDATA)> <!ELEMENT emp:projects (emp:project)*> <!ELEMENT emp:project (emp:product, emp:id, emp:price)> <!ELEMENT emp:product (#PCDATA)> <!ELEMENT emp:id (#PCDATA)> <!ELEMENT emp:price (#PCDATA)> ]> <emp:document xmlns:emp="http://www.xmlpowercorp.com/dtds/"> <emp:employee> <emp:name> <emp:lastname>Kelly</emp:lastname> <emp:firstname>Grace</emp:firstname> </emp:name> <emp:hiredate>October 15, 2005</emp:hiredate> <emp:projects> <emp:project> <emp:product>Printer</emp:product> <emp:id>111</emp:id> <emp:price>$111.00</emp:price> </emp:project> <emp:project> <emp:product>Laptop</emp:product> <emp:id>222</emp:id> <emp:price>$989.00</emp:price> </emp:project> </emp:projects> </emp:employee> . . . <emp:employee> <emp:name> <emp:lastname>Gable</emp:lastname> <emp:firstname>Clark</emp:firstname> </emp:name> <emp:hiredate>October 25, 2005</emp:hiredate> <emp:projects> <emp:project> <emp:product>Keyboard</emp:product> <emp:id>555</emp:id> <emp:price>$129.00</emp:price> </emp:project> <emp:project> <emp:product>Mouse</emp:product> <emp:id>666</emp:id> <emp:price>$25.00</emp:price> </emp:project> </emp:projects> </emp:employee> </emp:document>
As today's discussion shows, supporting namespaces in DTDs is not difficult; you just treat the namespace and colon as part of the name of an element. In fact, as shown here, you also treat attributes the same way. Tomorrow we'll talk about the idea of declaring attributes in DTDs.