2010-10-08 4 views
3

У меня возникли проблемы с загрузкой xml-файла с помощью php. Я использую DOMDocument, потому что мне нужна функция getElementsByTagName.
Я использую этот код. загрузить DOMDocument с HTML Специальные символы (php)

 
$dom = new DomDocument('1.0', 'UTF-8'); $dom->resolveExternals = false; $dom->load($_FILES["file"]["tmp_name"]);  
 
<?xml version="1.0" encoding="UTF-8"?> 
<Data> 
    <value>1796563</value> 
    <value>Verliebt! &rsquo;</value> 
</Data> 

ErrorMessage:
Внимание: DOMDocument :: нагрузки() [domdocument.load]: Объект 'Rsquo' не определен в/TMP/php1VRb3N, строка: 4 в/WWW/HTDOCS/бла/загрузки .php on line 51

ответ

1

Ваш XML-парсер не лжет. Это недопустимый (даже не корректный) документ, который вы не сможете загрузить ни с чем.

rsquo является предопределенным объектом в HTML, но не в XML. В XML-документе, если вы хотите использовать что-либо, кроме самых простых встроенных объектов (amp, lt, gt, quot и apos), вы должны определить их в DTD, на который ссылается объявление <!DOCTYPE>. (Вот как это делает XHTML.)

Вам нужно выяснить, откуда пришел вход и исправить все, что было ответственным за его создание, потому что на данный момент это просто не XML. Используйте ссылку на символ (&#8217;) или просто простой литерал в кодировке UTF-8.

В крайнем случае, если вы действительно должны принять это искаженный нонсенс для входа вы могли бы сделать противные строковые замены на файл:

$xml= file_get_contents($_FILES['file']['tmp_name']); 
$xml= str_replace('&rsquo;', '&#8217;', $xml); 
$dom->loadXML(xml); 

Если вам нужно сделать это для всех HTML сущностей не-XML а не только rsquo, это немного сложнее. Вы могли бы сделать регулярное выражение замены:

function only_html_entity_decode($match) { 
    if (in_array($match[1], array('amp', 'lt', 'gt', 'quot', 'apos'))) 
     return $match[0]; 
    else 
     return html_entity_decode($match[0], ENT_COMPAT, 'UTF-8'); 
} 
$xml= preg_replace_callback('/&(\w+);/', 'only_html_entity_decode', $xml); 

Это еще не велико, как это будет критикуют любые последовательности символов &\w+; в таких местах, как комментарии, разделы CDATA и НЦБ, где это не на самом деле означает образование Справка. Но это, вероятно, самое лучшее, что вы можете сделать, учитывая этот сломанный вход.

Это, безусловно, лучше, чем позвонить html_entity_decode по всему документу, что также испортит любые ссылки на сущности XML, в результате чего документ будет разбит всякий раз, когда есть существующие &amp; или &lt;.

Другим взломом, сомнительным по-разному, было бы загрузить документ, используя loadHTML().

+0

Спасибо за вашу помощь. – Bendim

2

Чтобы использовать этот объект, он должен быть определен в DTD. В противном случае это недопустимый XML. Если у вас нет DTD, вы должны декодировать объект до загрузки XML с DOM:

$dom->load(
    html_entity_decode(
     file_get_contents($_FILES["file"]["tmp_name"]), 
     ENT_COMPAT, 'UTF-8')); 
0

Мое решение с помощью bobince является:

$xml= file_get_contents($_FILES['file']['tmp_name']); 
    $xml= preg_replace('/&(\w+);/', '', $xml); 
    $dom = new DomDocument(); 
    $dom->loadXML($xml); 
+0

Это также выбросит все XML-предопределенные сущности, такие как '&' и' < '. Вы действительно уверены, что хотите это сделать? – bobince

+0

да, это нормально. в моих файлах нет XML-предопределенных имен сущностей, таких как '&' или '<'. – Bendim

Смежные вопросы