Причину $reader->read
, которая не восстанавливается после ошибок проверки схемы (даже если восстановление возможно), можно увидеть в строке # 8815 из LibXML.xs
. Обратите внимание, что REPORT_ERROR()
вызывается с нулевым значением (значение указывает, сможет ли `LibXML_report_error_ctx () восстанавливаться после ошибок или нет. Значение ноль означает, что оно не будет пытаться восстановить, иэто вызовет XML :: LibXML :: Error :: _ report_error , чтобы умереть.
Я попытался изменить значение на 1 в line # 8815 и перекомпилировал XSмодуль, и теперь он сообщил об ошибках схемы в виде предупреждений (вместо того, чтобы умереть) и продолжил анализ.
Я думаю, есть веская причина, почему эта опция не доступна для пользователя, но я не такзнакомый с синтаксическим анализом XML, я могу привести пример того, что здесь может пойти не так.
Редактировать :
Кажется, что правильный подход - перехватывать исключения, выдаваемыеread()
, затем попробуйте вызвать read()
в другой раз, если следующий вызов read()
вернет -1, парсер не сможет восстановиться после ошибки, если он вернет 0, достигнут конец файла,и если он вернет 1, то смогo оправиться от исключения. Я провел некоторое тестирование, и кажется, что оно способно восстановиться после ошибок проверки схемы, но не от ошибок анализа. Таким образом, вы можете попробовать следующее:
use feature qw(say);
use strict;
use warnings;
use Try::Tiny qw(try catch);
use XML::LibXML::Reader;
my $SchemaFile='schema.xsd';
my $FileToAnalyse='file.xml';
my $reader = XML::LibXML::Reader->new(
location => $FileToAnalyse, Schema => $SchemaFile
) or die "cannot read file '$FileToAnalyse': $!\n";
while (1) {
my $result;
try { $result = $reader->read } catch {
say '==> ' . $_;
$result = 1; # Try to continue after exception..
};
last if $result != 1;
if ( $reader->nodeType == XML_READER_ELEMENT ) {
say "Element node: ", $reader->name;
}
}
$reader->finish();
$reader->close();