Ejemplo 4: Validación con DTD

Define reglas de estructura para tu XML y valida documentos contra ellas

🎯 ¿En qué consiste este ejemplo?

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> con id obligatorio y, en este orden exacto, titulo, autor y anio. Elige una muestra o escribe tu propio XML, y PHP lo validará de verdad contra esa DTD usando DOMDocument::validate().

Elige o escribe un documento

Resultado de la validación

✅ XML válido El documento cumple todas las reglas de la DTD: elementos, orden y atributos obligatorios.

Documento enviado a validar

<?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>

📖 Explicación del Código

Código PHP Completo

<?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;
    }
}
?>

📝 La propia DTD

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

¿Qué hace? <!ELEMENT> declara que <libro> debe contener, en ese orden exacto, titulo, autor y anio. <!ATTLIST> declara que el atributo id es obligatorio (#REQUIRED).

💡 Concepto: contrato de estructura

Una DTD es un "contrato": cualquier XML que la use debe cumplirlo exactamente, incluido el orden de los elementos, algo que las tres muestras inválidas de este ejemplo incumplen a propósito.

📝 Validar con PHP

$esValido = $dom->validate();

¿Qué hace? Comprueba el documento cargado contra la DTD referenciada en su <!DOCTYPE> y devuelve true o false. Con libxml_use_internal_errors(true) los errores no se muestran directamente sino que se pueden recoger con libxml_get_errors().

🎯 Conceptos Clave Aprendidos

DTD

  • Define elementos, orden y atributos permitidos
  • Usa su propia sintaxis, no XML
  • Puede ser interna (<!DOCTYPE ... [ ]>) o externa

Validación en PHP

  • DOMDocument::validate()
  • libxml_use_internal_errors() para capturar errores
  • libxml_get_errors() lista los problemas

Bien formado vs. válido

  • "Bien formado": sintaxis XML correcta
  • "Válido": además, cumple una DTD/XSD
  • Un XML puede ser bien formado pero inválido

💪 Ejercicio Práctico

Rompe y arregla la validación

  1. Prueba las 4 muestras y lee el mensaje de error exacto que da libxml en cada caso
  2. Escribe en el editor un <libro> con un elemento repetido (por ejemplo, dos <titulo>) y observa el resultado
  3. Modifica mentalmente la DTD para que anio sea opcional. ¿Qué símbolo de DTD usarías? (pista: ?, * o +)

Hacer "anio" opcional

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

El símbolo ? significa "0 o 1 veces". * sería "0 o más" y + "1 o más".