XMLReader (в Php) и обработка ошибок

Быстрая версия:

Каков стандартный (новаторский? Любой?) способ обнаружения и обработки ошибок, выдаваемых XMLReader из-за неправильного формата файла, в частности, неэкранированных символов. Привлечение внимания с помощью Tidy (и т. Д.) Не очень привлекательный вариант, кто-нибудь знает способ просто пропустить оскорбительный узел и двигаться дальше?

Описательная версия:

Мы все знаем, что это не XML, если он неправильно сформирован, но давайте будем честными — такое случается. Клиент регулярно загружает массивные (50-100 МБ+) xml-файлы, которые необходимо прочитать в mysql. XMLReader — очевидный выбор, и мы написали оболочку, которая хорошо подходит для наших нужд.

Иногда возникает ошибка, и функция read() не завершает импорт — дерьмо! Это почти всегда неэкранированный символ (например, «&»), который сбивает все с толку. В большинстве случаев мы бы просто попросили клиента позвонить поставщику данных и потребовать исправить его дефектный файл. К сожалению, поставщики данных не всегда услужливы и/или своевременны. Было бы замечательно, если бы мы могли просто поймать ошибку и сразу перейти к следующему узлу.

Я потратил довольно много времени, пытаясь прочитать / взломать это, и не могу найти ничего стоящего. Я упускаю что-то очевидное?

Этот ТАК вопрос казался многообещающим, но он просто не дал никаких результатов. Кажется, что передача 1 должна попросить Reader восстановиться, но мы просто не видим никаких попыток/различных сообщений об ошибках и т. д. Вот соответствующий код, описывающий подход:

$xml->open($file, null, LIBXML_NOERROR | LIBXML_NOWARNING | 1);

Я всегда мог выполнить предварительную обработку с помощью Tidy, но должен быть способ получше.

Я рассмотрел несколько более «креативных» подходов, таких как прослушивание следующего Read() с помощью try/catch после завершения логики для текущего узла, но это кажется в лучшем случае неуклюжим. Также кажется, что может быть потенциал в эмуляции Read() с пользовательской функцией/оболочкой, которая помогает перемещаться по узлам и включает обработку ошибок, но у меня есть ощущение, что я слишком упрощаю вещи.

Итак, подведем итог: когда read() не работает, как я могу поймать ошибку и двигаться дальше? Есть ли шанс, что мы сможем увидеть, какая ошибка возникает (по крайней мере, сообщение, которое выдал бы XMLReader)?

$xml = new XMLReader();
$xml->open($file);

while ($xml->read()) {  

}

person quickquestion232342    schedule 26.08.2010    source источник


Ответы (3)


Это программа для чтения XML, и она предназначена для чтения XML. Недействительный XML не является XML и не может быть прочитан с помощью программы для чтения XML - это так просто.

Либо запустите xmllint в своем файле перед импортом, чтобы убедиться, что он действителен, либо сделайте все правильно и сообщите поставщику данных, чтобы он сгенерировал действительный xml.

person cweiske    schedule 01.03.2011

О части «увидеть ошибку» вашего вопроса:

http://php.net/manual/en/function.libxml-use-internal-errors.php Если для этого параметра установлено значение false по умолчанию, для любого недопустимого XML будет срабатывать предупреждение PHP. Другими словами, вы должны были это видеть :p Вы просто не обращали внимания, или у вас есть настройка или пользовательский обработчик ошибок, который скрывает от вас предупреждения PHP.

Если вы вызовете вышеуказанную функцию со значением true, предупреждение не будет сгенерировано, а вместо этого во внутреннем массиве, возвращаемом этой функцией, будут накапливаться ошибки:

http://www.php.net/manual/en/function.libxml-get-errors.php

Что касается части «движения вперед», я боюсь, что Цвейске был прав, и это невозможно сделать. Вы можете предварительно проверить свой XML на наличие ошибок с помощью какого-либо инструмента (даже проанализировав их с помощью XMLReader) и попытаться исправить найденные ошибки, то есть удалить/заменить недопустимые символы, но тогда вам нужно будет перезапустить анализ исправленных данных.

person grr    schedule 28.11.2012

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

Этот фильтр HTML в XML делает это. Используйте его как

$dsn = "php://filter/read=htmltoxml.entities/resource=" . $url;
$xml = XMLReader::open($dsn);
person Arnold Daniels    schedule 26.06.2014