2009-07-19 5 views
63

J'ai besoin d'analyser certains fichiers HTML, mais ils ne sont pas bien formés et PHP affiche des avertissements. Je veux éviter un tel comportement de débogage/avertissement par programme. S'il vous plaît donnez votre avis. Je vous remercie!Désactiver les avertissements lors du chargement de HTML non bien formé par DomDocument (PHP)

code:

// create a DOM document and load the HTML data 
$xmlDoc = new DomDocument; 
// this dumps out the warnings 
$xmlDoc->loadHTML($fetchResult); 

Ce:

@$xmlDoc->loadHTML($fetchResult) 

peut supprimer les mises en garde, mais comment puis-je capturer ces avertissements programatically?

+0

Essayez cette solution - semble être beaucoup plus facile - http://stackoverflow.com/questions/6090667/php-domdocument-errors-warnings-on-html5-tags – Marcin

+0

Conversion entrée moche à la sortie proprement dit est ce paye les factures;) L'option [recover est dans le manuel] (http://nl1.php.net/manual/en/class.domdocument.php#domdocument.props.recover). c'est juste un booléen. Vous pouvez simplement appeler '$ dom-> saveHTML()' pour voir de quelle sorte le document libxml essaye de faire de votre entrée '$ html', habituellement c'est assez proche/ok. – Wrikken

Répondre

16

Vous pouvez installer un gestionnaire d'erreur temporaire avec set_error_handler

class ErrorTrap { 
    protected $callback; 
    protected $errors = array(); 
    function __construct($callback) { 
    $this->callback = $callback; 
    } 
    function call() { 
    $result = null; 
    set_error_handler(array($this, 'onError')); 
    try { 
     $result = call_user_func_array($this->callback, func_get_args()); 
    } catch (Exception $ex) { 
     restore_error_handler();   
     throw $ex; 
    } 
    restore_error_handler(); 
    return $result; 
    } 
    function onError($errno, $errstr, $errfile, $errline) { 
    $this->errors[] = array($errno, $errstr, $errfile, $errline); 
    } 
    function ok() { 
    return count($this->errors) === 0; 
    } 
    function errors() { 
    return $this->errors; 
    } 
} 

Utilisation:

// create a DOM document and load the HTML data 
$xmlDoc = new DomDocument(); 
$caller = new ErrorTrap(array($xmlDoc, 'loadHTML')); 
// this doesn't dump out any warnings 
$caller->call($fetchResult); 
if (!$caller->ok()) { 
    var_dump($caller->errors()); 
} 
+0

Merci! Un truc si sympa! Le code est simple et propre. – Viet

+7

On dirait beaucoup de surpuissance pour la situation. Notez les fonctions libxml2 de PHP. – thomasrutter

+0

Bon point, Thomas. Je ne connaissais pas ces fonctions quand j'ai écrit cette réponse. Si je ne me trompe pas, il fait la même chose en interne. – troelskn

184

Appel

libxml_use_internal_errors(true); 

avant le traitement avec des $xmlDoc->loadHTML()

Cela indique à libxml2 not to send les erreurs et les avertissements à travers PHP. Ensuite, pour vérifier les erreurs et les gérer vous-même, vous pouvez consulter libxml_get_last_error() et/ou libxml_get_errors() lorsque vous êtes prêt.

+17

@ Viet- cela devrait * probablement * être la réponse acceptée ... – Ben

75

Pour masquer les avertissements, vous devez donner des instructions spéciales pour libxml qui est utilisé en interne pour effectuer l'analyse syntaxique:

libxml_use_internal_errors(true); 
$dom->loadHTML($html); 
libxml_clear_errors(); 

Le libxml_use_internal_errors(true) indique que vous allez gérer les erreurs et les avertissements vous et vous Je ne veux pas qu'ils gâchent la sortie de votre script.

Ce n'est pas la même chose que l'opérateur @. Les avertissements sont collectés dans les coulisses et ensuite vous pouvez les récupérer en utilisant libxml_get_errors() dans le cas où vous souhaitez effectuer une journalisation ou retourner la liste des problèmes à l'appelant.

Que vous utilisiez ou non les avertissements collectés, vous devez toujours effacer la file d'attente en appelant le libxml_clear_errors().

Préserver l'état

Si vous avez autre code qui utilise libxml il peut être utile de vous assurer que votre code ne modifie pas l'état global de la gestion des erreurs; pour cela, vous pouvez utiliser la valeur de retour de libxml_use_internal_errors() pour enregistrer l'état précédent.

// modify state 
$libxml_previous_state = libxml_use_internal_errors(true); 
// parse 
$dom->loadHTML($html); 
// handle errors 
libxml_clear_errors(); 
// restore 
libxml_use_internal_errors($libxml_previous_state); 
+1

Devrais-je utiliser libxml_use_internal_errors (false); lorsque vous avez terminé? – Greeso

+2

@Greeso: Il est défini sur la valeur * précédente *. Cela est fait par le concept qu'il pourrait avoir été configuré pour un autre code globalement différent de 'FALSE' et le mettre à' FALSE' par la suite détruirait ce paramètre. En utilisant la valeur de retour précédente '$ libxml_previous_state', ces effets secondaires potentiels sont évités car la configuration d'origine a été restaurée indépendamment de ce lieu. Le paramètre 'libxml_use_internal_errors()' est global, il vaut donc la peine d'y faire attention. – hakre

+0

S'il y a déjà des erreurs libxml en attente, cela ne les mange-t-il pas? – cHao

Questions connexes