No history yet

Structural Integrity with DTD

The Blueprint for Your Data

You know that an XML document needs to be well-formed, with every tag properly nested and closed. But being well-formed isn't enough for serious data exchange. It's like having a sentence with correct grammar but no meaning. For data to be reliable, it also needs to be valid.

A valid XML document conforms to a predefined structure, a set of rules that act as a contract between the sender and receiver. The classic way to define this contract is with a Document Type Definition (DTD). A DTD is the blueprint for your XML, specifying which elements are allowed, what they can contain, and how they relate to one another.

An XML Schema describes the structure of an XML document.

Think of it as the difference between a pile of bricks and a finished house. Both are made of the same materials, but only one has the structural integrity to be useful. A DTD provides that integrity for your data.

Lesson image

Internal vs External DTDs

You can include your DTD directly inside your XML file or link to it as a separate file. Including it inside is called an internal subset. This is convenient for small, self-contained documents where the rules won't be reused.

You define it within the DOCTYPE declaration, right after the root element name.

<?xml version="1.0"?>
<!DOCTYPE note [
  <!ELEMENT note (to, from, heading, body)>
  <!ELEMENT to      (#PCDATA)>
  <!ELEMENT from    (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body    (#PCDATA)>
]>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

More commonly, you'll use an external subset. The DTD lives in its own .dtd file, and the XML document links to it. This approach is far more scalable, allowing many XML documents to share the same set of rules. This ensures consistency across an entire system or organization.

To link an external DTD, you use the SYSTEM keyword followed by the DTD's file path.

<!-- In note.xml -->
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>
<!-- In note.dtd -->
<!ELEMENT note (to, from, heading, body)>
<!ELEMENT to      (#PCDATA)>
<!ELEMENT from    (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body    (#PCDATA)>

Defining the Structure

A DTD is built from a few key declaration types that define the elements, attributes, and entities of your XML.

Element Type Declarations This is the core of the DTD. It specifies the name of an element and what it's allowed to contain. The content can be other elements, text, or a mix of both.

  • (#PCDATA): This stands for Parsed Character Data and means the element can contain text that will be parsed by the XML processor. Think of it as standard text content.
  • (child1, child2): This defines a strict sequence of child elements.
  • (child1 | child2): This allows one child element or another.
  • EMPTY: The element must be empty (e.g., <br />).
  • ANY: The element can contain any combination of text and other elements. Use this sparingly, as it weakens the validation.

You can also add quantifiers to control how many times a child element can appear:

  • +: One or more times.
  • *: Zero or more times.
  • ?: Zero or one time.
<!-- A report can have a title, one or more authors, and an optional summary, followed by the body -->
<!ELEMENT report (title, author+, summary?, body)>

<!-- A title contains only text -->
<!ELEMENT title (#PCDATA)>

<!-- An author contains only text -->
<!ELEMENT author (#PCDATA)>

<!-- A summary contains only text -->
<!ELEMENT summary (#PCDATA)>

<!-- The body can contain any mix of elements -->
<!ELEMENT body ANY>

Attribute-List Declarations Elements often have attributes that provide metadata. The ATTLIST declaration defines the attributes for a specific element, including their name, data type, and default behavior.

TypeDescription
CDATAThe attribute value is simple character data (text).
`(val1val2
IDA unique identifier for the element within the document.
IDREFA reference to another element's ID.
IDREFSA space-separated list of references to other IDs.
NMTOKENA name token (a limited string with no spaces).
NMTOKENSA space-separated list of name tokens.

You also specify a default value for each attribute:

DefaultDescription
"value"A default value if the attribute isn't specified.
#REQUIREDThe attribute must be included.
#IMPLIEDThe attribute is optional.
#FIXED "value"The attribute must have this exact value if present.
<!ELEMENT payment (amount, currency)>
<!ATTLIST payment
  type (credit | debit | cash) #REQUIRED
  transaction_id ID #REQUIRED
  status CDATA "pending"
>

Entity Declarations Entities are variables or shortcuts. They allow you to define a piece of text or markup once and reuse it throughout your document. This is incredibly useful for things like boilerplate text, special characters, or external content.

A common use is to define a short, readable name for a special character. You define it in the DTD and then reference it in your XML using an ampersand and a semicolon.

<!-- In the DTD -->
<!ENTITY copyright "© 2024 My Company"> 

<!-- In the XML -->
<footer>&copyright;</footer>

When the XML is processed, &copyright; will be replaced with "© 2024 My Company". This ensures consistency and makes updating recurring information trivial—you only have to change it in one place.

Well-Formed vs. Valid

It's crucial to understand the distinction between a well-formed document and a valid one.

A well-formed XML document follows all the basic syntax rules of XML. It has a single root element, all elements are properly nested, every tag has a corresponding closing tag, and attribute values are quoted. An XML parser will reject any document that isn't well-formed.

A valid XML document is a step beyond that. Not only is it well-formed, but it also adheres to all the rules defined in its DTD. An element that the DTD forbids, a missing required attribute, or an element in the wrong order will all cause a validating parser to report an error.

Every valid XML document is, by definition, well-formed. But not every well-formed document is valid. Validation is an optional but powerful step to ensure data quality and between different systems.

It's time to check what you've learned.

Quiz Questions 1/6

What is the primary difference between a well-formed XML document and a valid XML document?

Quiz Questions 2/6

In a DTD, what does the (#PCDATA) keyword signify within an element declaration?

Using a DTD imposes a strict, predictable structure on your data. This blueprint ensures that anyone consuming your XML knows exactly what to expect, preventing errors and making your data far more reliable.