Отключить предупреждения при загрузке неправильно сформированного HTML с помощью DOMDocument (PHP)


Мне нужно проанализировать некоторые HTML-файлы, однако они плохо сформированы, и PHP выводит предупреждения. Я хочу программно избежать такого поведения отладки/предупреждения. Пожалуйста, посоветуйте. Спасибо!

Код:

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

Это:

@$xmlDoc->loadHTML($fetchResult)

Можно подавлять предупреждения, но как я могу захватить эти предупреждения программно?

Author: thomasrutter, 2009-07-19

4 answers

Вы можете установить временный обработчик ошибок с помощью 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;
  }
}

Использование:

// 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());
}
 14
Author: troelskn, 2009-07-19 14:21:36

Вызов

libxml_use_internal_errors(true);

Перед обработкой с помощью $xmlDoc->loadHTML()

Это говорит libxml2 не отправлять ошибки и предупреждения в PHP. Затем, чтобы проверить наличие ошибок и обработать их самостоятельно, вы можете обратиться к libxml_get_last_error() и/или libxml_get_errors(), когда будете готовы.

 194
Author: thomasrutter, 2010-05-17 06:54:28

Чтобы скрыть предупреждения, вы должны дать специальные инструкции libxml, который используется внутренне для выполнения синтаксического анализа:

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

В libxml_use_internal_errors(true) указывает, что вы собираетесь самостоятельно обрабатывать ошибки и предупреждения и не хотите, чтобы они испортили вывод вашего скрипта.

Это не то же самое, что оператор @. Предупреждения собираются за кулисами, а затем вы можете получить их с помощью libxml_get_errors() на случай, если вы захотите выполните ведение журнала или верните список проблем вызывающему абоненту.

Независимо от того, используете ли вы собранные предупреждения, вы всегда должны очищать очередь, вызывая libxml_clear_errors().

Сохранение государства

Если у вас есть другой код, который использует libxml, возможно, стоит убедиться, что ваш код не изменяет глобальное состояние обработки ошибок; для этого вы можете использовать возвращаемое значение libxml_use_internal_errors() для сохранения предыдущего состояния.

// 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);
 85
Author: Ja͢ck, 2013-11-26 02:00:09

Настройка параметров "LIBXML_NOWARNING" и "LIBXML_NOERROR" также отлично работает:

$dom->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR);
 2
Author: Joshua Ott, 2018-08-03 06:50:30