Получение XMLReader PHP для того, чтобы не вызывать ошибки php в недопустимых документах

Я нахожусь в написании парсера и стараюсь делать хорошую обработку ошибок с исключениями.

Следующий пример кода:

<?php $xml = <<<XML <?xml version="1.0"?> <rootElem> XML; $reader = new XMLReader(); $reader->xml($xml, null, LIBXML_NOERROR | LIBXML_NOWARNING); $reader->read(); 

Выдает:

 PHP Warning: XMLReader::read(): An Error Occured while reading in /Users/evert/code/xml/errortest.php on line 11 PHP Stack trace: PHP 1. {main}() /Users/evert/code/xml/errortest.php:0 PHP 2. XMLReader->read() /Users/evert/code/xml/errortest.php:11 

Добавление:

 libxml_use_internal_errors(true); 

Не имеет никакого эффекта.

Моя цель – проверить ошибки позже (с помощью libxml_get_errors() ) и выбросить исключение. Я считаю, что единственным решением является использование оператора молчания ( @ ), но это похоже на плохую идею.

Обратите внимание, что когда я не LIBXML константы LIBXML и не использую libxml_use_internal_errors , я получаю другую ошибку, например:

 PHP Warning: XMLReader::read(): /Users/evert/code/xml/:2: parser error : Extra content at the end of the document in /Users/evert/code/xml/errortest.php on line 11 

Это говорит о том, что основная библиотека libxml действительно подавляет ошибку, но в XMLReader все равно возникает ошибка.

Похоже, нет способа подавить предупреждение, кроме использования @ , поскольку источник php для read() имеет следующие строки:

 retval = xmlTextReaderRead(intern->ptr); if (retval == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading"); RETURN_FALSE; } else { RETURN_BOOL(retval); } 

Таким образом, только фактические ошибки синтаксического анализа внутри xmlTextReaderRead() подавляются libxml_use_internal_errors(true); или параметры, переданные в XMLReader::xml() .

Из моего понимания XMLReader, чтобы проверить документ, необходимо выполнить один полный проход по всему документу.

Что я делаю:

 // Enable internal libxml errors libxml_use_internal_errors(true); $xml = new \XMLReader(); $xsd='myfile.xsd'; $xml->open('myfile.xml'); $xml->setSchema ($xsd); // Conduct full pass through document. The only reason is to force validation. while (@$xml->read()) { }; // empty loop if (count(libxml_get_errors ())==0) { echo "provided xml is well formed and xsd-valid"; // Now you can start processing without @ as document was validated against xsd and is xml-wellformed } else echo "provided xml is wrong and/or not xsd-valid. stopping"; 

Конечно, вы можете проверить ошибки внутри пустого цикла, а затем сразу же после первой ошибки сломаться. Я заметил, что XMLReader не полностью сбой после первой ошибки – он продолжается и приносит множество проблем, которые полезны. Иногда может быть полезно распечатать все обнаруженные проблемы вместо обработки прерывания после первой проблемы.

Моя самая большая проблема заключается в том, что функция isValid существует в XMLReader 🙂 Я думаю, что это на самом деле своего рода обходной путь, но он работает очень хорошо и проверяет до того, как обработка соответствует 95% случаев использования XMLReader, поскольку она используется для обработки больших XML-коллекций.