Получение 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.