2009-07-19 2 views
63

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

Код:

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

Это:

@$xmlDoc->loadHTML($fetchResult) 

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

+0

Попробуйте это решение - кажется, гораздо проще - http://stackoverflow.com/questions/6090667/php-domdocument-errors-warnings-on-html5-tags – Marcin

+0

Преобразования паршивого входа в правильный выход, что оплачивает счета;) [вариант восстановления находится в руководстве] (http://nl1.php.net/manual/en/class.domdocument.php#domdocument.props.recover). это просто логическое значение. Вы можете просто вызвать '$ dom-> saveHTML()', чтобы посмотреть, какой тип, если document libxml пытается сделать ваш вход '$ html', обычно он довольно близок/ok. – Wrikken

ответ

16

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

Спасибо! Такой аккуратный трюк! Код прост и чист. – Viet

+7

Похоже на много переполнения ситуации. Обратите внимание на функции libxml2 PHP. – thomasrutter

+0

Хорошая точка, Томас. Я не знал об этих функциях, когда писал этот ответ. Если я не ошибаюсь, он делает то же самое внутренне кстати. – troelskn

184

Вызов

libxml_use_internal_errors(true); 

до обработки с с $xmlDoc->loadHTML()

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

+17

@ Viet- это должно * вероятно, быть принятым ответом ... – Ben

75

Чтобы скрыть предупреждения, вы должны дать специальные инструкции 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); 
+1

Должен ли я использовать libxml_use_internal_errors (false); когда это делается? – Greeso

+2

@Greeso: он установлен в значение * previous *. Это делается по понятию, что он может быть настроен для какого-либо другого кода, глобально отличающегося от FALSE, и затем после установки FALSE уничтожит эту настройку. Используя предыдущее возвращаемое значение '$ libxml_previous_state', эти потенциальные побочные эффекты предотвращаются, потому что исходная конфигурация была восстановлена ​​независимо от этого места. Параметр 'libxml_use_internal_errors()' является глобальным, поэтому стоит позаботиться об этом. – hakre

+0

Если есть ошибки libxml в ожидании, не будет ли это их есть? – cHao

 Смежные вопросы

  • Нет связанных вопросов^_^