Validar XML utilizando una DTD personalizada en PHP

¿Hay alguna manera (sin instalar ninguna biblioteca) de validar XML utilizando una DTD personalizada en PHP?

Eche un vistazo al DOM de PHP , especialmente DOMDocument :: schemaValidate y DOMDocument :: validate .

El ejemplo de DOMDocument :: validate es bastante simple:

Load('book.xml'); if ($dom->validate()) { echo "This document is valid!\n"; } ?> 

Si tiene el dtd en una cadena, puede validarlo utilizando un contenedor de datos para la dtd:

 $xml = '   Tove Jani Reminder Don\'t forget me this weekend! '; $dtd = '    '; $root = 'note'; $systemId = 'data://text/plain;base64,'.base64_encode($dtd); $old = new DOMDocument; $old->loadXML($xml); $creator = new DOMImplementation; $doctype = $creator->createDocumentType($root, null, $systemId); $new = $creator->createDocument(null, null, $doctype); $new->encoding = "utf-8"; $oldNode = $old->getElementsByTagName($root)->item(0); $newNode = $new->importNode($oldNode, true); $new->appendChild($newNode); if (@$new->validate()) { echo "Valid"; } else { echo "Not valid"; } 

Mi interpretación de la pregunta original es que tenemos un archivo XML “a bordo” que queremos validar contra un archivo DTD “a bordo”. Así que aquí es cómo implementaría la idea de “interpolar una DTD local dentro del elemento DOCTYPE” expresada en los comentarios de Soren y PayamRWD:

 función pública validate ($ xml_realpath, $ dtd_realpath = null) {
     $ xml_lines = archivo ($ xml_realpath);
     $ doc = new DOMDocument;
     if ($ dtd_realpath) {
         // Inyectar DTD dentro de la línea DOCTYPE:
         $ dtd_lines = archivo ($ dtd_realpath);
         $ new_lines = array ();
         foreach ($ xml_lines as $ x) {
             // Asumir el formato DOCTYPE SYSTEM "blah blah":
             if (preg_match ('/ DOCTYPE /', $ x)) {
                 $ y = preg_replace ('/ SYSTEM "(. *)" /', "[\ n". implode ("\ n", $ dtd_lines). "\ n]", $ x);
                 $ new_lines [] = $ y;
             } else {
                 $ new_lines [] = $ x;
             }
         }
         $ doc-> loadXML (implode ("\ n", $ new_lines));
     } else {
         $ doc-> loadXML (implode ("\ n", $ xml_lines));
     }
     // Habilitar el manejo de error del usuario
     libxml_use_internal_errors (true);
     if (@ $ doc-> validate ()) {
         echo "¡válido! \ n";
     } else {
         echo "No válido: \ n";
         $ errors = libxml_get_errors ();
         foreach ($ errors as $ error) {
             print_r ($ error, true);
         }
     }
 }

Tenga en cuenta que el manejo de errores se ha suprimido por brevedad, y que puede haber una forma mejor / más general de manejar la interpolación. Pero en realidad he usado este código con datos reales, y funciona con PHP versión 5.2.17.

Intentando completar la respuesta “owenmarshall”:

en xml-validator.php:

agregar html, encabezado, cuerpo, …

  $dom->Load('template-format.xml');
if ($dom->validate()) {
echo "This document is valid!\n";
} ?>

template-format.xml:

     





]>