Получение 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_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 все равно возникает ошибка.
2 ответов
похоже, что нет никакого способа подавить предупреждение, кроме как использовать @
, так как 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 не терпит неудачу полностью после первой ошибки - он продолжается и приносит множество проблем, которые полезны. Иногда может быть полезно распечатать все найденные проблемы вместо break обработка после первой проблемы.
моя самая большая проблема заключается в том, что для функции isValid существует в XMLReader :) Я думаю, что это на самом деле своего рода обходной путь, но он работает очень хорошо и проверяет перед обработкой 95% случаев использования XMLReader, поскольку он используется для обработки больших коллекций xml.