ПРОБЛЕМА
- Функция PHP
simplexml_load_file
выдает ошибку синтаксического анализа parser
error : xmlParseEntityRef
при попытке загрузить файл XML с URL-адреса.
ПРИЧИНА
- XML, возвращаемый URL-адресом, не является допустимым XML. Содержит значение
&
вместо &
. Вполне возможно, что есть другие ошибки, которые не очевидны в данный момент.
ВЕЩИ НАШЕГО КОНТРОЛЯ
- В идеале, мы должны убедиться, что в функцию PHP
simplexml_load_file
передается действительный XML, но похоже, что мы не имеем никакого контроля над тем, как создается XML.
- Также невозможно заставить
simplexml_load_file
обработать
неверный файл XML. Это не оставляет нам много вариантов, кроме
исправление самого файла XML.
ВОЗМОЖНОЕ РЕШЕНИЕ
Преобразование неверного XML в действительный XML. Это можно сделать с помощью PHP tidy extension
. Дальнейшие инструкции можно найти по http://php.net/manual/en/book.tidy.php
Если вы уверены, что расширение существует или установлено, выполните следующие действия.
/**
* As per the question asked, the URL is loaded into a variable first,
* which we can assume to be $xml
*/
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<project orderno="6" campaign_name="International Relief & Development for under developed nations">
<invalid-data>Some other data containing & in it</invalid-data>
<unclosed-tag>
</project>
XML;
/**
* Whenever we use tidy it is best to pass some configuration options
* similar to $tidyConfig. In this particular case we are making sure that
* tidy understands that our input and output is XML.
*/
$tidyConfig = array (
'indent' => true,
'input-xml' => true,
'output-xml' => true,
'wrap' => 200
);
/**
* Now we can use tidy to parse the string and then repair it.
*/
$tidy = new tidy;
$tidy->parseString($xml, $tidyConfig, 'utf8');
$tidy->cleanRepair();
/**
* If we try to output the repaired XML string by echoing $tidy it should look like.
<?xml version="1.0" encoding="utf-8"?>
<project orderno="6" campaign_name="International Relief & Development for under developed nations">
<invalid-data>Some other data containing & in it</invalid-data>
<unclosed-tag></unclosed-tag>
</project>
* As you can see that & is now fixed in campaign_name attribute
* and also with-in invalid-data element. You can also see that the
* <unclosed-tag> which didn't had a close tag, has been fixed too.
*/
echo $tidy;
/**
* Now when we try to use simplexml_load_string to load the clean XML. When we
* try to print_r it should look something like below.
SimpleXMLElement Object
(
[@attributes] => Array
(
[orderno] => 6
[campaign_name] => International Relief & Development for under developed nations
)
[invalid-data] => Some other data containing & in it
[unclosed-tag] => SimpleXMLElement Object
(
)
)
*/
$simpleXmlElement = simplexml_load_string($tidy);
print_r($simpleXmlElement);
ВНИМАНИЕ
Разработчик должен попытаться сравнить недопустимый XML с действительным XML (сгенерированным tidy), чтобы убедиться в отсутствии побочных эффектов после использования tidy. Tidy делает очень хорошую работу, делая это правильно, но никогда не помешает увидеть это визуально и быть на 100% уверенным. В нашем случае это должно быть так же просто, как сравнивать $ xml с $ tidy.