89 votes

Désactiver les avertissements lors du chargement de HTML non bien formé par DomDocument (PHP)

Je dois analyser certains fichiers HTML, cependant, ils ne sont pas bien formés et PHP génère des avertissements. Je veux éviter ce comportement de débogage/avertissement de manière programmatique. S'il vous plaît conseillez-moi. Je vous remercie!

Code:

// crée un document DOM et charge les données HTML
$xmlDoc = new DomDocument;
// cela affiche les avertissements
$xmlDoc->loadHTML($fetchResult);

Cela:

@$xmlDoc->loadHTML($fetchResult)

peut supprimer les avertissements mais comment puis-je capturer ces avertissements de manière programmatique?

1 votes

Essayez cette solution - semble être beaucoup plus facile - stackoverflow.com/questions/6090667/…

0 votes

Transformer une mauvaise entrée en une sortie correcte est ce qui paie les factures ;) L'option recover est dans le manuel. c'est juste un booléen. Vous pouvez simplement appeler $dom->saveHTML() pour voir quel genre de document libxml essaie de créer à partir de votre entrée $html, habituellement c'est assez proche/correct.

245voto

thomasrutter Points 42905

Appel

libxml_use_internal_errors(true);

avant de traiter avec $xmlDoc->loadHTML()

Cela dit à libxml2 de ne pas envoyer les erreurs et avertissements à 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 :

libxml_use_internal_errors(true);
$dom->loadHTML($html);
$errors = libxml_get_errors();
foreach ($errors as $error) {
    // gérer les erreurs comme vous le souhaitez
}

2 votes

C'est tellement plus facile que d'ajouter 20 lignes de code comme le fait la réponse acceptée. Merci!

0 votes

Qu'est-il arrivé au tri dans la pile récemment. Cette réponse la plus votée est en bas

99voto

Jack Points 88446

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

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

La libxml_use_internal_errors(true) indique que vous allez gérer les erreurs et avertissements vous-même et que vous ne voulez pas qu'ils perturbent la sortie de votre script.

Ce n'est pas la même chose que l'opérateur @. Les avertissements sont collectés en arrière-plan et ensuite vous pouvez les récupérer en utilisant libxml_get_errors() si vous souhaitez effectuer un journal ou renvoyer la liste des problèmes à l'appelant.

Que vous utilisiez ou non les avertissements collectés, vous devriez toujours vider la file en appelant libxml_clear_errors().

Préservation de l'état

Si vous avez d'autres codes qui utilisent libxml, il peut être utile de vous assurer que votre code n'altère pas l'état global de la gestion des erreurs ; pour cela, vous pouvez utiliser la valeur de retour de libxml_use_internal_errors() pour sauvegarder l'état précédent.

// modifier l'état
$libxml_previous_state = libxml_use_internal_errors(true);
// analyser
$dom->loadHTML($html);
// gérer les erreurs
libxml_clear_errors();
// restaurer
libxml_use_internal_errors($libxml_previous_state);

2 votes

@Greeso: Il est défini sur la valeur précédente. Cela est fait par le concept selon lequel il aurait pu être configuré pour un autre code globalement différent de FALSE et le définir par la suite sur FALSE 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 initiale a été restaurée de manière indépendante des besoins de cet endroit. Le paramètre libxml_use_internal_errors() est global, il vaut donc la peine de faire attention.

0 votes

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

0 votes

@cHao n'est-il pas raisonnable de supposer que vous commencez à partir d'une page vierge? :)

46voto

Joshua Ott Points 805

Définir les options "LIBXML_NOWARNING" et "LIBXML_NOERROR" fonctionne également parfaitement :

$dom->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR);

13voto

troelskn Points 51966

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:

// créer un document DOM et charger les données HTML
$xmlDoc = new DomDocument();
$caller = new ErrorTrap(array($xmlDoc, 'loadHTML'));
// cela ne génère aucun avertissement
$caller->call($fetchResult);
if (!$caller->ok()) {
  var_dump($caller->errors());
}

10 votes

Il semble que ce soit beaucoup trop pour la situation. Notez les fonctions libxml2 de PHP.

0 votes

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

1 votes

Il a le même effet dans ce cas oui, bien que cela se fasse à un niveau différent : avec la solution ci-dessus, des erreurs PHP sont générées mais supprimées, tandis qu'avec la mienne, elles ne deviennent pas des erreurs PHP. Personnellement, je pense que si faire quelque chose implique de supprimer les erreurs PHP soit par @ soit par set_error_handler(), alors c'est la mauvaise façon de le faire. C'est juste mon opinion cependant. Notez que les erreurs PHP et les exceptions sont deux choses totalement différentes - utiliser try {} catch(){} est correct.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X