Example 4: DTD Validation

Define structural rules for your XML and validate documents against them

🎯 What does this example cover?

Un DTD (Document Type Definition) declara qué elementos puede tener un documento XML, en qué orden y con qué atributos obligatorios. Este ejemplo usa una DTD fija (la puedes ver más abajo) que exige un <libro> with id obligatorio y, en este orden exacto, titulo, autor and anio. Elige una muestra o escribe tu propio XML, y PHP lo validará de verdad contra esa DTD usando DOMDocument::validate().

Choose or write a document

Validation result

✅ XML válido The document meets all the DTD's rules: elements, order and required attributes.

Document submitted for validation

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE libro [
<!ELEMENT libro (titulo, autor, anio)>
<!ATTLIST libro id CDATA #REQUIRED>
<!ELEMENT titulo (#PCDATA)>
<!ELEMENT autor (#PCDATA)>
<!ELEMENT anio (#PCDATA)>
]>
<libro id="001">
    <titulo>El Quijote</titulo>
    <autor>Miguel de Cervantes</autor>
    <anio>1605</anio>
</libro>

📖 Code Explanation

Complete PHP Code

<?php
libxml_use_internal_errors(true);

$dom = new DOMDocument();
$dom->loadXML($xmlConDtd);

$esValido = $dom->validate();

if (!$esValido) {
    foreach (libxml_get_errors() as $error) {
        echo $error->message;
    }
}
?>

📝 The DTD itself

<!ELEMENT libro (titulo, autor, anio)>
<!ATTLIST libro id CDATA #REQUIRED>

What does it do? <!ELEMENT> declares that <libro> must contain, in this exact order, titulo, autor and anio. <!ATTLIST> declares that the id attribute is required (#REQUIRED).

💡 Concept: structural contract

A DTD is a "contract": any XML that uses it must follow it exactly, including element order, which the three invalid samples in this example deliberately break.

📝 Validate with PHP

$esValido = $dom->validate();

What does it do? Checks the loaded document against the DTD referenced in its <!DOCTYPE> and returns true or false. With libxml_use_internal_errors(true) errors aren't shown directly but can be collected with libxml_get_errors().

🎯 Key Concepts Learned

DTD

  • Defines allowed elements, order and attributes
  • Uses its own syntax, not XML
  • Can be internal (<!DOCTYPE ... [ ]>) or external

Validation in PHP

  • DOMDocument::validate()
  • libxml_use_internal_errors() to capture errors
  • libxml_get_errors() lists the problems

Well-formed vs. valid

  • "Well-formed": correct XML syntax
  • "Valid": additionally, follows a DTD/XSD
  • An XML document can be well-formed but invalid

💪 Practical Exercise

Break and fix the validation

  1. Try the 4 samples and read the exact error message libxml gives in each case
  2. Write in the editor a <libro> with a repeated element (for example, two <titulo>) and observe the result
  3. Mentally modify the DTD so that anio becomes optional. Which DTD symbol would you use? (hint: ?, * or +)

Make "anio" optional

<!ELEMENT libro (titulo, autor, anio?)>

The symbol ? means "0 or 1 times". * would mean "0 or more" and + "1 or more".