2010-07-22 13 views
5

Tout le monde sait que nous devrions toujours utiliser les techniques DOM au lieu d'expressions rationnelles pour extraire le contenu de HTML, mais j'ai l'impression que je ne peux jamais faire confiance à l'extension SimpleXML ou similaires.Bulletproofing SimpleXMLElement

Je coder une mise en œuvre OpenID en ce moment, et j'essayé d'utiliser SimpleXML pour faire la découverte HTML - mais mon premier test (avec alixaxel.myopenid.com) a donné beaucoup d'erreurs:

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 

Je me souviens qu'il y avait un moyen de rendre SimpleXML toujours analyser un fichier, indépendamment si le document contient des erreurs ou non - Je ne me souviens pas de l'implémentation spécifique, mais je pense que cela impliquait l'utilisation de DOMDocument. Quelle est la meilleure façon de s'assurer que SimpleXML analyse toujours un document donné?

Et s'il vous plaît ne suggère pas d'utiliser Tidy, je pense que l'extension est lente et il n'est pas disponible sur de nombreux systèmes.

Répondre

10

Vous pouvez charger le code HTML avec DOM's loadHTML puis importer le résultat dans SimpleXML.

IIRC, il va encore étouffer certains choses mais il acceptera à peu près tout ce qui existe dans le monde réel des sites Web brisés.

$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! C'est mieux ... Est-ce que cette solution est à l'épreuve des balles? Puis-je lui faire confiance pour analyser n'importe quel document? –

+0

@Alix probablement pas * tout * document. Si le HTML est trop cassé, alors c'est trop cassé. Mais pour la plupart des HTML cassés cela devrait fonctionner. Une alternative serait d'utiliser XmlReader. C'est un analyseur d'extraction qui vous permet de définir ce qu'il faut faire sur quel élément. Il existe également un certain nombre d'options de configuration pour l'extension libxml sous-jacente que vous pouvez utiliser pour influencer l'analyse. – Gordon

0

vous pouvez toujours essayer un analyseur SAX ... Un peu plus robuste aux erreurs.

Peut ne pas être aussi efficace sur du grand XML.