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
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
<!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
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 errorslibxml_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
- Try the 4 samples and read the exact error message libxml gives in each case
- Write in the editor a
<libro>with a repeated element (for example, two<titulo>) and observe the result - Mentally modify the DTD so that
aniobecomes 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".