2010-07-22 12 views
5

Todo el mundo sabe que siempre debemos usar técnicas DOM en lugar de expresiones regulares para extraer contenido de HTML, pero me da la sensación de que nunca puedo confiar en la extensión SimpleXML o similares.Bulletproofing SimpleXMLElement

estoy codificación de una aplicación de OpenID en este momento, y yo intentado usar SimpleXML para hacer el descubrimiento HTML - pero mi primera prueba (con alixaxel.myopenid.com) produjo una gran cantidad de errores:

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 27: parser error : Opening and ending tag mismatch: link line 11 and head in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: </head> in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 64: parser error : Entity 'copy' not defined in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: &copy; 2008 <a href="http://janrain.com/">JanRain, Inc.</a> in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 66: parser error : Entity 'trade' not defined in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: myOpenID&trade; and the myOpenID&trade; website are in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 66: parser error : Entity 'trade' not defined in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: myOpenID&trade; and the myOpenID&trade; website are in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 77: parser error : Opening and ending tag mismatch: link line 8 and html in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: </html> in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 78: parser error : Premature end of data in tag head line 3 in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 78: parser error : Premature end of data in tag html line 2 in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]: in E:\xampplite\htdocs\index.php on line 6 

Warning: simplexml_load_string() [function.simplexml-load-string]:^in E:\xampplite\htdocs\index.php on line 6 

Recuerdo que había una manera de hacer que SimpleXML siempre analizara un archivo, independientemente de si el documento contiene errores o no. Sin embargo, no recuerdo la implementación específica, pero creo que involucró el uso de DOMDocument. ¿Cuál es la mejor manera de asegurarse de que SimpleXML siempre analiza cualquier documento dado?

Y por favor no sugiera usar Tidy, creo que la extensión es lenta y no está disponible en muchos sistemas.

Respuesta

10

Puede cargar el HTML con DOM's loadHTML y luego importar el resultado a SimpleXML.

IIRC, todavía asfixiará en algunas cosas pero aceptará casi todo lo que existe en el mundo real de sitios web rotos.

$html = '<html><head><body><div>stuff & stuff</body></html>'; 

// disable PHP errors 
$old = libxml_use_internal_errors(true); 

$dom = new DOMDocument; 
$dom->loadHTML($html); 

// restore the old behaviour 
libxml_use_internal_errors($old); 

$sxe = simplexml_import_dom($dom); 
die($sxe->asXML()); 
+0

Uff! Eso es mejor ... ¿Es esta solución * a prueba de balas *? ¿Puedo confiar en que analizará cualquier documento? –

+0

@Alix bien probablemente no * cualquier * documento. Si el HTML está demasiado roto, entonces está demasiado roto. Pero para la mayoría de los HTML rotos esto debería funcionar. Una alternativa sería usar XmlReader. Es un analizador de extracción que te permite definir qué hacer en qué elemento. También hay una serie de opciones de configuración para la extensión libxml subyacente que puede utilizar para influir en el análisis sintáctico. – Gordon

0

siempre puedes probar un analizador SAX ... Un poco más robusto a los errores.

Puede que no sea tan eficiente en XML grandes.

Cuestiones relacionadas