2009-08-13 26 views
10

En PHP, estoy tratando de validar un documento XML utilizando una DTD especificada por mi aplicación, no por el documento XML extraído externamente. El método de validación en la clase DOMDocument parece validar únicamente utilizando la DTD especificada por el documento XML en sí, por lo que esto no funcionará.Validación XML contra una DTD dada en PHP

¿Se puede hacer esto, y cómo, o tengo que traducir mi DTD a un esquema XML para que pueda usar el método schemaValidate?

(esto parece haber sido invitado en Validate XML using a custom DTD in PHP pero sin respuesta correcta, ya que la solución sólo se basa en la DTD speicified por el XML de destino)

+4

¿Se puede añadir su DTD para el XML de destino. ¡Cree un documento vacío con su DTD y luego cargue su XML objetivo en el documento vacío – rojoca

Respuesta

16

Nota: XML validation podría estar sujeto al ataque Billion Laughs y vectores DoS similares .

Esto esencialmente hace lo rojoca mencionó en su comentario:

<?php 

$xml = <<<END 
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE foo SYSTEM "foo.dtd"> 
<foo> 
    <bar>baz</bar> 
</foo> 
END; 

$root = 'foo'; 

$old = new DOMDocument; 
$old->loadXML($xml); 

$creator = new DOMImplementation; 
$doctype = $creator->createDocumentType($root, null, 'bar.dtd'); 
$new = $creator->createDocument(null, null, $doctype); 
$new->encoding = "utf-8"; 

$oldNode = $old->getElementsByTagName($root)->item(0); 
$newNode = $new->importNode($oldNode, true); 
$new->appendChild($newNode); 

$new->validate(); 

?> 

Esto validará el documento en contra de la bar.dtd.

No se puede llamar $new->loadXML(), porque eso acaba de establecer el DTD a la original, y la propiedad doctype de un objeto DOMDocument es de sólo lectura, por lo que tiene que copiar el nodo raíz (con todo su contenido) a un nuevo documento DOM.

Solo he tenido éxito con esto, por lo que no estoy del todo seguro de si esto cubre todo, pero definitivamente funciona para el XML en mi ejemplo.

Por supuesto, la solución rápida y sucia sería obtener primero el XML como una cadena, buscar y reemplazar la DTD original por su propia DTD y luego cargarla.

+0

, muy buen ejemplo! Muchas gracias. – Allanrbo

+0

+1 para el método rápido y sucio -> buscar y reemplazar. –

Cuestiones relacionadas