Skip to content

DTD Validation — Complete Guide to Document Type Definitions

DodaTech Updated 2026-06-23 9 min read

In this tutorial, you'll learn about DTD Validation. We cover key concepts, practical examples, and best practices.

DTD (Document Type Definition) validation defines the legal structure of an XML document using declarations for elements, attributes, entities, and notations — enforcing business rules before data processing.

What You'll Learn

  • Writing DTD element and attribute declarations
  • Internal vs external DTDs and how to link them
  • Entity declarations for reusable content and character references
  • Validating XML against DTDs with tools and code

Why DTD Validation Matters

DTD validation ensures XML data meets structural requirements before your application processes it. A missing required element or an unexpected attribute can crash a parser, corrupt data, or create security vulnerabilities. Durga Antivirus Pro uses DTD validation as a first-pass check on XML threat signature files — rejecting malformed updates before they reach the scan engine.

Learning Path

flowchart LR
  A[XML Basics] --> B[XML DTD Doctype]
  B --> C[DTD Validation
You are here] C --> D[XML Schema XSD] D --> E[SOAP & WSDL]

DTD Syntax Reference

Declaration Syntax Purpose
Element <!ELEMENT name content> Define element structure
Attribute <!ATTLIST elem name type default> Define element attributes
Entity <!ENTITY name value> Define reusable content
Notation <!NOTATION name system> Define data format

Complete DTD Example

<!ELEMENT library (book+)>
<!ELEMENT book (title, author, year, price)>
<!ATTLIST book
    category (fiction|non-fiction|sci-fi) "fiction"
    id ID #IMPLIED>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST price
    currency (USD|EUR|GBP|JPY) "USD">

Let's break down each declaration:

  • <!ELEMENT library (book+)> — library contains one or more book elements
  • <!ELEMENT book (title, author, year, price)> — book must have title, author, year, price in sequence
  • <!ATTLIST book category (fiction|non-fiction|sci-fi) "fiction"> — category attribute, default "fiction"
  • <!ATTLIST book id ID #IMPLIED> — optional ID attribute of type ID (unique)
  • <!ELEMENT title (#PCDATA)> — title contains parsed character data (text)
  • <!ATTLIST price currency (USD|EUR|GBP|JPY) "USD"> — currency attribute with enumerated values

Internal DTD

An internal DTD is declared inside the XML document itself:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library [
    <!ELEMENT library (book+)>
    <!ELEMENT book (title, author, year, price)>
    <!ATTLIST book category (fiction|non-fiction) "fiction">
    <!ELEMENT title (#PCDATA)>
    <!ELEMENT author (#PCDATA)>
    <!ELEMENT year (#PCDATA)>
    <!ELEMENT price (#PCDATA)>
]>
<library>
    <book category="fiction">
        <title>The Hobbit</title>
        <author>J.R.R. Tolkien</author>
        <year>1937</year>
        <price currency="USD">12.99</price>
    </book>
    <book category="non-fiction">
        <title>A Brief History of Time</title>
        <author>Stephen Hawking</author>
        <year>1988</year>
        <price currency="GBP">9.99</price>
    </book>
</library>

Internal DTDs are useful for standalone documents that don't need to share validation rules.

External DTD

External DTDs are stored in separate .dtd files and referenced from XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library SYSTEM "library.dtd">
<library>
    <book category="fiction" id="b1">
        <title>The Hobbit</title>
        <author>J.R.R. Tolkien</author>
        <year>1937</year>
        <price currency="USD">12.99</price>
    </book>
</library>

The library.dtd file:

<!ELEMENT library (book+)>
<!ELEMENT book (title, author, year, price)>
<!ATTLIST book
    category (fiction|non-fiction|sci-fi) "fiction"
    id ID #IMPLIED>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST price
    currency (USD|EUR|GBP|JPY) "USD">

External DTDs are the standard for enterprise use — one schema file validates thousands of documents.

Element Content Models

DTD defines several content models for elements:

Model Syntax Example Meaning
Empty EMPTY <!ELEMENT br EMPTY> No content allowed
Text-only (#PCDATA) <!ELEMENT title (#PCDATA)> Only text
Element-only (child1, child2) <!ELEMENT book (title, author)> Only children in order
Mixed (#PCDATA\|child)* <!ELEMENT p (#PCDATA\|b\|i)*> Text or children, any order
Any ANY <!ELEMENT wrapper ANY> Any content (avoid)

Occurrence Indicators

Symbol Meaning
+ One or more (required, repeatable)
* Zero or more (optional, repeatable)
? Zero or one (optional)
(none) Exactly one (required)
<!ELEMENT library (book+)>           <!-- One or more books -->
<!ELEMENT catalog (book*, magazine*)> <!-- Zero or more of each -->
<!ELEMENT chapter (title, para+)>   <!-- One title, one or more paras -->
<!ELEMENT reference (author?)>      <!-- Optional author -->

Attribute Types

Type Description Example
CDATA Character data (text) <!ATTLIST book isbn CDATA #REQUIRED>
ID Unique identifier <!ATTLIST book id ID #REQUIRED>
IDREF Reference to an ID <!ATTLIST chapter ref IDREF #IMPLIED>
IDREFS Space-separated ID list <!ATTLIST book crossRefs IDREFS #IMPLIED>
(val1\|val2) Enumerated values <!ATTLIST book category (fiction\|non-fiction) "fiction">
NMTOKEN Name token (letters, digits) <!ATTLIST part code NMTOKEN #REQUIRED>
ENTITY Entity reference <!ATTLIST img src ENTITY #REQUIRED>

Attribute Defaults

Default Meaning
#REQUIRED Attribute must be present
#IMPLIED Attribute is optional
"value" Default value if not specified
#FIXED "value" Attribute must have this value

Entity Declarations

Entities define reusable content or special characters:

<!-- General entities (used in XML content) -->
<!ENTITY author-name "DodaTech Tutorials">
<!ENTITY copyright "Copyright 2026, DodaTech.">

<!-- Parameter entities (used only in DTD) -->
<!ENTITY % book-model "(title, author, year, price)">
<!ELEMENT book %book-model;>

<!-- External entities (refer to external files) -->
<!ENTITY logo SYSTEM "logo.svg" NDATA SVG>
<!ENTITY disclaimer SYSTEM "disclaimer.xml">

Using entities in XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article [
    <!ENTITY author "DodaTech">
    <!ENTITY version "1.0">
]>
<article>
    <title>XML DTD Guide v&version;</title>
    <author>&author;</author>
    <body>This guide covers DTD validation.</body>
</article>

Expected output when parsed:

<?xml version="1.0" encoding="UTF-8"?>
<article>
    <title>XML DTD Guide v1.0</title>
    <author>DodaTech</author>
    <body>This guide covers DTD validation.</body>
</article>

Validating XML with Tools

The xmllint command validates XML against DTD:

# Validate with internal DTD
xmllint --valid --noout document.xml

# Validate with external DTD
xmllint --dtdvalid library.dtd --noout library.xml

# Show validation output
xmllint --dtdvalid library.dtd library.xml

Expected output for valid XML:

(no output — exit code 0)

Expected output for invalid XML:

library.xml:5: element year: validity error: Element year content does not follow
  the DTD, expecting (#PCDATA), got '19xy'
library.xml fails to validate

Validating with Python

from lxml import etree

# Parse DTD
dtd = etree.DTD(open('library.dtd', 'rb').read())

# Parse XML
xml = etree.parse('library.xml')

# Validate
if dtd.validate(xml):
    print("XML document is valid against the DTD.")
else:
    print("Validation errors:")
    for error in dtd.error_log.filter_from_errors():
        print(f"  Line {error.line}: {error.message}")

# Expected output (valid):
# XML document is valid against the DTD.

# Expected output (invalid):
# Validation errors:
#   Line 3: Element book content does not follow the DTD,
#   expecting (title, author, year, price), got (title, author, price, year)

Security Angle

DTDs can be dangerous. External entity references in DTDs enable XXE attacks:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

This DTD instructs the parser to read /etc/passwd and include its contents. Durga Antivirus Pro strips DTD declarations from untrusted XML files before processing and validates all XML against a predefined schema rather than allowing inline DTDs. Always disable external entity resolution on production parsers.

DTD vs XSD

Feature DTD XSD (XML Schema)
Syntax Non-XML (custom) XML
Data types Only text (PCDATA) Strings, numbers, dates, etc.
Namespace support No Yes
Extensibility Limited Via inheritance and substitution
Regex patterns No Yes (via pattern facet)
Documentation No Via xs:annotation
Processing Parsers support universally Requires schema-aware parser

Common Mistakes

1. Forgetting the DOCTYPE declaration

Without <!DOCTYPE ...>, the parser does not validate. It checks well-formedness only.

2. Wrong order of child elements in content model

(title, author, year, price) requires this exact order. If the XML has (title, year, author, price), validation fails.

3. Using #PCDATA in an element that needs children

(#PCDATA) means text only. For child elements, use the element names. For mixed content, use (#PCDATA|child)*.

4. Not using + for required repeated elements

(book) means exactly one book. (book+) means one or more. (book*) means zero or more. Choose the right indicator.

5. Forgetting that DTD is not namespace-aware

DTD treats xmlns:prefix="uri" as an attribute named xmlns:prefix. It does not understand XML namespaces.

Practice Questions

  1. What is the difference between internal and external DTD? Internal DTD is declared inside the XML document using <!DOCTYPE ... [...]>. External DTD is a separate .dtd file referenced by SYSTEM or PUBLIC identifier.

  2. What does the + indicator mean in a DTD content model? One or more occurrences of the preceding element. For example, (book+) means at least one book is required.

  3. What is an XXE attack and how does it relate to DTD? XXE (XML External Entity) attacks use DTD entity declarations to read local files or perform SSRF attacks by referencing external resources. Prevention requires disabling external entity resolution.

Challenge: Write a DTD for an invoice XML that includes an invoice number (required ID), date (required), customer name and address, one or more line items (each with product code, description, quantity, unit price), and a total. Add attribute validations for currency and tax rate.

FAQ

What is a DTD in XML?

A Document Type Definition defines the legal structure, elements, attributes, and entities of an XML document using a non-XML syntax.

How do I validate XML against a DTD?

Use xmllint --dtdvalid file.dtd file.xml on the command line, or use lxml's DTD class in Python.

What is the difference between DTD and XML Schema?

DTD uses custom syntax, has no data types beyond text, and lacks namespace support. XML Schema uses XML syntax, supports rich datatypes, and handles namespaces.

What is #PCDATA in DTD?

Parsed Character Data — text content that the XML parser processes (as opposed to CDATA sections that are passed through unparsed).

Can DTD enforce data types like numbers or dates?

No. DTD only supports text content (#PCDATA). For data type validation, use XML Schema (XSD).

What is an external entity in DTD?

An entity that references content from an external file or URL. External entities are the basis of XXE attacks and should be disabled in secure parsing.

Try It Yourself

Validate an XML file with an external DTD:

# Create library.dtd
cat > library.dtd << 'EOF'
<!ELEMENT library (book+)>
<!ELEMENT book (title, author, year, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT price (#PCDATA)>
EOF

# Create XML referencing the DTD
cat > test.xml << 'EOF'
<?xml version="1.0"?>
<!DOCTYPE library SYSTEM "library.dtd">
<library>
    <book><title>Test</title><author>Me</author><year>2026</year><price>9.99</price></book>
</library>
EOF

# Validate
xmllint --valid --noout test.xml && echo "Valid!"

What's Next

Tutorial What You'll Learn
XML Basics — Complete Guide Foundational XML concepts
XML Schema Datatypes Advanced XSD datatypes and validation
XPath Explained — Querying XML Navigate XML documents with path expressions

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-23.

What's Next

Congratulations on completing this DTD Validation tutorial! Here's where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Create a DTD for a real data format like a recipe catalog
  • Explore related topics — Check out other XML tutorials in this category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro