DTD stands for Document Type Definition. In short, it defines the structure of an XML document.

With a DTD, we specify which elements, attributes, entities, and tree structures are allowed in the XML document.

This gives the document a standard structure and makes validation possible.

XML Building Blocks

  • Elements
  • Attributes
  • Entities
  • PCDATA
  • CDATA

We will look at how these building blocks are defined in a DTD.

Elements

<!ELEMENT element-name element-content>

The general syntax for defining an element looks like this. To define an empty element:

<!ELEMENT element-name EMPTY>
Example:
<!ELEMENT br EMPTY>
<br />

To define an element that contains PCDATA:

<!ELEMENT element-name (#PCDATA)>
Example:
<!ELEMENT title (#PCDATA)>

To define an element that can contain any content, use ANY:

<!ELEMENT element-name ANY>
Example:
<!ELEMENT book ANY>

When an element contains other elements, those nested elements are child elements. To define an element with child elements:

<!ELEMENT element-name (child1,child2...)>
Example:
<!ELEMENT book (title,author,language,edition,date)>

Let's expand this with a simple book structure:

<!ELEMENT books (book)>
<!ELEMENT book (title,author,language,edition,date)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT language (#PCDATA)>
<!ELEMENT edition (#PCDATA)>
<!ELEMENT date (year,month,day)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT month (#PCDATA)>
<!ELEMENT day (#PCDATA)>

If an element can contain one or more instances of the same child element, add + after the child element.

<!ELEMENT books (book+)>
<!ELEMENT book (title,author,language,edition,date)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT language (#PCDATA)>
<!ELEMENT edition (#PCDATA)>
<!ELEMENT date (year,month,day)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT month (#PCDATA)>
<!ELEMENT day (#PCDATA)>

Use * for zero or more elements.

<!ELEMENT element-name (child*)>
Example:
<!ELEMENT books (book*)>

Use ? for zero or one element.

<!ELEMENT element-name (child?)>
Example:
<!ELEMENT books (book?)>

To allow one of multiple child elements, use | as an "or" operator.

<!ELEMENT element-name (child1|child2)>
Example:
<!ELEMENT book (edition|isbn)>

Attributes

<!ATTLIST element-name attribute-name attribute-type attribute-value>

The attribute definition syntax looks like this. Example:

<!ATTLIST book isbn ID "9759954949">
XML:
<book isbn="9759954949"></book>

Attribute Types

TypeDescription
CDATACharacter data
(option1 | option2 | ...)The value must be one of the listed options
IDMust be a unique value
IDREFThe ID of another element
IDREFSIDs of multiple other elements
NMTOKENA valid XML name token
NMTOKENSA list of valid XML name tokens
ENTITYAn entity
ENTITIESMultiple entities
NOTATIONA notation

Attribute Values

ValueDescription
valueDefault value
#REQUIREDRequired value
#IMPLIEDOptional value
#FIXEDFixed value

We do not need to try every attribute type here. A few examples are enough, and we already used ID above.

Now let's define an attribute with type ID and value #REQUIRED.

<!ATTLIST element-name attribute-name ID #REQUIRED>
DTD:
<!ATTLIST book isbn ID #REQUIRED>
XML:
<book isbn="9759954949"></book>

Entities

<!ENTITY entity-name "entity-value">
DTD:
<!ENTITY book "Yunus Emre Divani">
XML:
<books>&book;</books>

To reference an external entity:

<!ENTITY entity-name SYSTEM "ADDRESS">
DTD:
<!ENTITY book SYSTEM "https://example.com/book.dtd">
XML:
<books>&book;</books>

Now that we have covered the basics of DTD, let's reinforce them with an example. We will add a DTD to the library example used earlier.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE books [
<!ELEMENT books (book+)>
<!ELEMENT book (title,author,language,edition,date)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT language (#PCDATA)>
<!ELEMENT edition (#PCDATA)>
<!ELEMENT date (year,month,day)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT month (#PCDATA)>
<!ELEMENT day (#PCDATA)>

<!ATTLIST book isbn ID #REQUIRED>
<!ATTLIST author role CDATA #IMPLIED>
]>
<books>
    <book isbn="9759954949">
        <title>Yunus Emre Divani</title>
        <author role="Editor">Selim Yagmur</author>
        <language>Turkish</language>
        <edition>8</edition>
        <date>
            <year>2014</year>
            <month>04</month>
            <day>01</day>
        </date>
    </book>
    <book isbn="9753386203">
        <title>Risaletun-Nushiyye Yunus Emre</title>
        <author role="Translator">Prof. Dr. Umay Turkes Gunay</author>
        <language>Turkish</language>
        <edition>3</edition>
        <date>
            <year>2009</year>
            <month>01</month>
            <day>01</day>
        </date>
    </book>
</books>

If we want to store the DTD file in a separate location:

<!DOCTYPE books SYSTEM "ADDRESS">

How can we check whether the DTD we wrote is valid?

You can use this validator: http://www.w3schools.com/xml/xml_validator.asp