Ever tried to read a DTD, and failed miserably? Ever wondered what all those symbols and weird language constructs meant? Well, fear not - this crash course will get you up to speed with the basics of DTD design in a hurry.
Just as you can declare elements, a DTD also allows you to define the attributes attached to each element. An attribute declaration typically looks like this:
<!-- element declarations -->
<!ELEMENT weather (city, temperature, forecast)>
<!ELEMENT
city (#PCDATA)>
<!ELEMENT forecast (#PCDATA)>
<!ELEMENT high (#PCDATA)>
<!ELEMENT
low (#PCDATA)>
<!ELEMENT temperature (high, low)>
<!-- attribute declarations
-->
<!ATTLIST city state CDATA #REQUIRED>
<!ATTLIST high units CDATA #REQUIRED>
<!ATTLIST
low units CDATA #REQUIRED>
Let's examine the first one a little more closely:
<!ATTLIST city state CDATA #REQUIRED>
In English, this declares that the element "city" has an attribute named "state"
containing character data. The additional #REQUIRED modifier indicates that this is a required attribute - failure to include it will render the XML document invalid.
A number of different content types are available for attributes. You're already familiar with character data - here's a quick list of the others:
type description
------------------------------------------
CDATA character
data
ID unique identifier
IDREF reference to unique identifier of another element
IDREFS
list
of identifiers
NMTOKEN string literal or token
NMTOKENS list of tokens
ENTITY
entity
ENTITIES list
of entities
You can also specify a list of allowed attribute values by enclosing them in
parentheses and separating them with the | operator. The following attribute declaration does just that, limiting the list of allowed values for the "units" attribute to either "celsius" or "fahrenheit".
<!ATTLIST high units (celsius | fahrenheit) #REQUIRED>
A number of modifiers are available, each applying a special characteristic to
the attribute. For example, you can specify a default value for the attribute by enclosing it in quotes; this default value is used if the attribute is absent.
<!ATTLIST high units (celsius | fahrenheit) "fahrenheit">
The #IMPLIED modifier is used to declare a particular attribute as optional.
<!ATTLIST high units #IMPLIED>
And finally, the #FIXED keyword is used to fix an attribute value to something
specific, allowing the XML document author no choice in the matter.
<!ATTLIST high units (celsius | fahrenheit) #FIXED "fahrenheit">
If an element has more than one attribute, you can declare them all within the
same attribute declaration. Consider the following XML document,
and its associated DTD, which demonstrates how this works.
<!-- element declarations -->
<!ELEMENT movie (title, cast, director)>
<!ELEMENT
title (#PCDATA)>
<!ELEMENT cast (#PCDATA)>
<!ELEMENT director (#PCDATA)>
<!--
attribute declarations -->
<!ATTLIST movie
id CDATA #REQUIRED
genre CDATA
#REQUIRED