Строка не может быть проанализирована как XML в большом файле XML, обработанном PHP CLI

В настоящее время у меня проблема с импортом большого XML-файла, и я не могу понять, почему. Мы получаем вывод XML от партнера размером около 443 МБ. Ошибка, которую я получаю, выглядит следующим образом:

PHP Warning:  SimpleXMLElement::__construct(): Entity: line 1: parser error : internal error in /home/imports/catalog.php on line 54

Warning: SimpleXMLElement::__construct(): Entity: line 1: parser error : internal error in /home/imports/catalog.php on line 54
PHP Warning:  SimpleXMLElement::__construct(): ch to marriage, parenting, entrepreneurship, etc will be significantly upgraded. in /home/imports/catalog.php on line 54

Warning: SimpleXMLElement::__construct(): ch to marriage, parenting, entrepreneurship, etc will be significantly upgraded. in /home/imports/catalog.php on line 54
PHP Warning:  SimpleXMLElement::__construct():
 ^ in /home/imports/catalog.php on line 54

Warning: SimpleXMLElement::__construct():
 ^ in /home/imports/catalog.php on line 54
PHP Fatal error:  Uncaught exception 'Exception' with message 'String could not be parsed as XML' in /home/imports/catalog.php:54
Stack trace:
#0 /home/imports/catalog.php(54): SimpleXMLElement->__construct('<?xml version="...')
#1 {main}
  thrown in /home/imports/catalog.php on line 54

Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in /home/imports/catalog.php:54
Stack trace:
#0 /home/imports/catalog.php(54): SimpleXMLElement->__construct('<?xml version="...')
#1 {main}
  thrown in /home/imports/catalog.php on line 54

Строка 54 кода проста:

$xml = new SimpleXMLElement(file_get_contents($_CFG_XML_URL));

Насколько я могу судить, ошибка в элементе, содержащем ch to marriage, parenting, entrepreneurship, etc will be significantly upgraded.. К сожалению, это длинный путь к файлу, и из-за его размера трудно прочитать содержимое. Моя программа для чтения больших файлов читает построчно, а весь этот XML находится в одной строке, так что это слишком сложно для корректной обработки даже на рабочей станции с 32 ГБ ОЗУ и 64-разрядным редактором.

Я пытался перезагрузить файл несколько раз, но проблема всегда одна и та же. Я удвоил доступную память для сценария, и он все еще не работает в том же месте.

Итак, я связался с партнером и попросил XML для этого конкретного элемента, и они предоставили следующее:

<EBook EAN="9792219192201">
    <Title>Success-a-Phobia</Title>
    <SubTitle>Discovering And Conquering Mankinds Most Persuasive, but Unknown, Phobia</SubTitle>
    <Publisher>The Benjamin Consulting Group, LLC</Publisher>
    <PublicationDate>29/09/2012</PublicationDate>
    <Contributors>
        <Contributor Code="A01" Text="By (author)">Benjamin, Marcus D.</Contributor>
    </Contributors>
    <Formats>
        <Format Type="6"/>
    </Formats>
    <ShortDescription>People today still desire to be successful in matters of family, finance or business even though we are in the midst of major social, political and economic challenges. Have you every been at that moment where you wanted to do something significant, yet you were paralyzed from making the necessary choices to realize your dream? Have you experienced failure and are now sitting in the stands, paralyzed from getting back in the &amp;quote;game of life?&amp;quote;  Are you at the verge of a major decision that could affect your life for many years? If you are in this category, this is your book of the year!    With humor, real-life antidotes, real-life examples and solid narration, Marcus Benjamin will guide you toward discovering the most pervasive, yet unknown, phobia in the history of mankind.  Once this phobia is discovered, the second half of the book shows you how to rid yourself of this phobia for good. Not only will this book impact your life, but your approach to marriage, parenting, entrepreneurship, etc will be significantly upgraded.</ShortDescription>
</EBook>

Ничто в этом XML не тревожит меня, но явно на полпути к PHP возникла проблема. Похоже, что в содержимом элемента содержится 978 символов, но это не вызывает у меня никаких особых тревожных сигналов.

Сценарий PHP запускается из командной строки в экземпляре Amazon EC2. ОС — Amazon Linux (RHEL).

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


person Engineer81    schedule 20.12.2012    source источник
comment
Предоставленный вами xml отлично работает для меня. codepad.viper-7.com/suwsVY   -  person Jonathan Kuhn    schedule 20.12.2012
comment
Единственное, что я могу придумать, это открыть файл в текстовом редакторе, вытащить большой кусок и попытаться загрузить его заново. Подобно бинарному поиску, удалите последнюю половину. Если ошибок нет, удалите первую половину и попробуйте вторую половину. работайте вниз, пока не найдете проблему. Если обе половины работают нормально, возможно, это просто размер файла, но я в этом сомневаюсь, потому что не вижу ошибок распределения памяти. Если какая-либо половина выдает ошибку, разрезайте ее пополам снова и снова, пока не найдете проблему. Скорее всего, это недопустимый узел xml.   -  person Jonathan Kuhn    schedule 20.12.2012
comment
@JonathanKuhn - это отличная идея. Работать с этим файлом не так просто из-за его размера, но я попробую. Конечно, самый простой вариант для начала, я думаю   -  person Engineer81    schedule 20.12.2012
comment
Кроме того, есть функция simplexml_load_file(), которая возвращает экземпляр simplexml. Я сомневаюсь, что это проблема, поскольку эта функция должна делать то же самое, но может помочь.   -  person Jonathan Kuhn    schedule 20.12.2012
comment
Мой опыт работы с большими файлами XML заключается в том, что вам лучше использовать xml_read для файлов размером более ~ 50 МБ. Это намного быстрее и использует очень мало памяти. Но с ним менее гибко работать.   -  person Green Black    schedule 20.12.2012
comment
@JonathanKuhn - Ваше предложение заставило меня задуматься ... Я смог загрузить только последние пару МБ файла в свой редактор, чтобы им было легче управлять, и я обнаружил, что это самый последний элемент. Поэтому я только что удалил его и повторно загружаю файл для обработки.   -  person Engineer81    schedule 20.12.2012
comment
@John - Обычно у нас не возникает проблем с файлами XML такого размера. У нас есть некоторые из них размером более 100 ГБ, которые мы импортируем в MySQL с помощью XML2DB, а затем вместо этого обрабатываем данные оттуда, но мы никогда не нуждались в них для такого маленького файла.   -  person Engineer81    schedule 20.12.2012
comment
@JonathanKuhn - я удалил этот последний элемент ‹EBook/›, а затем тот, который стал последним, вызвал аналогичную ошибку. Теперь я удалил все остальные элементы ‹Электронной книги/›, так что остался только первоначальный проблемный элемент, и кажется, что он работает без проблем (это только одна фаза более крупного процесса, и он обычно завершается сбоем за считанные секунды, на этот раз это некоторое время бегает). Таким образом, проблема, похоже, связана с размером, а не с фактическим содержанием. Нужно посмотреть, какие значения я могу изменить, чтобы решить. Возможно, проблема с окружением. Мячи!   -  person Engineer81    schedule 20.12.2012
comment
Возможно, тогда нужно будет вырезать больший разрез. Как я уже говорил ранее, я не думаю, что это размер, а плохо сформированный xml просто потому, что нет ошибок памяти. Возможно, это отсутствие закрывающего тега xml или какого-либо узла, вокруг которого должен быть тег cdata. Я бы предложил что-то вроде деления xml-узлов пополам и после этого проверки файла. Если у вас есть доступ по ssh, вы можете использовать что-то вроде head, чтобы получить первые -n NNN строк и передать их в файл. затем очистите файл, удалив последний частичный элемент и добавив окончательный закрывающий тег (и) xml. возможно, найдите инструмент проверки xml.   -  person Jonathan Kuhn    schedule 20.12.2012
comment
stackoverflow.com/questions/7528249 /   -  person Jonathan Kuhn    schedule 21.12.2012
comment
В нем говорится, что ошибка находится в строке 1, исходный XML без разрывов строк? Кроме того, вам, вероятно, следует использовать simplexml_load_file вместо file_get_contents.   -  person dualed    schedule 21.12.2012
comment
@dualed - Да, все это в одной строке, поэтому у меня проблемы с моим редактором больших файлов, который любит читать построчно. Я переключил его на simplexml_load_file(), чтобы посмотреть, имеет ли какое-то значение просто потому, что это быстро и легко сделать, и я могу оставить его работающим, чтобы посмотреть, как он работает. Если это снова не удастся, я попытаюсь разрезать его на более мелкие кусочки, как предложил Джонатан.   -  person Engineer81    schedule 21.12.2012
comment
Интересно ... @JonathanKuhn - Вы думали, что SimpleXML_Load_File() не будет иметь никакого значения, но я запустил его час назад, и я только что пришел проверить, и, похоже, он работает. Хотя это отличный результат, я все же хотел бы знать, почему другой метод не работает, поскольку он работал на другой нашей платформе в прошлом, поэтому, очевидно, что-то не так. В любом случае, я счастливый кролик прямо сейчас!   -  person Engineer81    schedule 21.12.2012
comment
И скрипт успешно завершился?   -  person dualed    schedule 21.12.2012
comment
Он все еще работает. Предстоит большая обработка, включая загрузку изображений с серверов провайдеров. Похоже, что эта фаза завершилась нормально, да.   -  person Engineer81    schedule 21.12.2012
comment
Я не могу сказать наверняка, что сделал трюк. Но поскольку file_get_contents считывает весь файл в память, а затем вы передаете его в SimpleXML, даже если PHP соберет строку, в конечном итоге он сможет сделать это только после того, как SimpleXML завершит ее разбор. Таким образом, вам нужно как минимум на несколько сотен МБ памяти меньше.   -  person dualed    schedule 21.12.2012
comment
PHP настроен на этой машине, чтобы иметь возможность использовать до 6 ГБ, поэтому я не думаю, что это проблема с памятью. Интересно, это как-то связано с используемым нами инстансом Amazon EC2? Но тогда мы используем m1.large, поэтому я уверен, что это не так.   -  person Engineer81    schedule 21.12.2012


Ответы (2)


Попробуйте проверить xml, используя xmllint. он доступен как инструмент командной строки для Linux.

Если файл верный. Вы должны дважды проверить, если ваш memory_limit ini var. Помните, что обработка DOM (как и простой xml) требует, чтобы весь файл находился в памяти. В вашем случае memory_limit должен быть установлен как минимум на 500 МБ.

Если вы не можете увеличить лимит памяти, вам придется рассмотреть способ с меньшим потреблением памяти для анализа xml. В этой ситуации может подойти SAX, хотя он требует большего внимания к программированию.

В PHP SAX доступен через расширение xml и включен по умолчанию. Здесь вы можете найти документацию.

person hek2mgl    schedule 20.12.2012
comment
Я не пробовал. Однако, похоже, он работал нормально, когда $xml = new SimpleXMLElement(file_get_contents($_CFG_XML_URL)); был заменен на $xml = new SimpleXML_Load_File($_CFG_XML_URL);. - person Engineer81; 21.12.2012
comment
какая версия libxml использует php? какой ос вы пользуетесь? - person hek2mgl; 21.12.2012
comment
2.7.8 согласно phpinfo(). Как и в исходном вопросе: Amazon Linux на EC2 - person Engineer81; 21.12.2012
comment
В ПОРЯДКЕ. Без файла xml я не могу больше сказать об этом. Может быть проблема с libxml или PHP. Однако у вас все получилось.. - person hek2mgl; 21.12.2012

978 может и не звонить в колокола, но 1000 может! 4 пробела в начале строки, а затем 18 символов для «‹ShortDescription›» дадут необходимые 22 символа. Круглое число, такое как 1000, может увеличить вероятность некоторого ограничения длины буфера.

person arayq2    schedule 21.12.2012
comment
Не является ли необычным, что значения 1000 являются проблемой? Я ожидаю, что это более вероятно при 1024 или подобном. Кроме того, удалив этот элемент с конца, мы обнаружили, что предыдущий вызывает ту же проблему, но имеет совершенно другой размер. Это просто очень странно и было решено переключением на SimpleXML_Load_File(). О, и впереди нет пробелов, потому что все это находится на одной строке, где один элемент следует сразу за другим. - person Engineer81; 22.12.2012