PHP XML Entity не определена проблема разбора с simplexml_load_string и SimpleXMLElement addChild / addAttribute

0

Использование PHP 5.3.13

simplexml_load_string бросает сущность "делить" не определенную ошибку при анализе xml.

В большинстве решений этой проблемы основное внимание уделяется тому, как обращаться с SimpleXMLElement и его методами addChild и addAttribue. Эти методы преобразуют некоторые специальные символы в объекты. Решение, похоже, говорит о том, чтобы иметь дело с несколькими специальными символами, которые simplexml_load_string не понимает.

Проблема в том, что список очень велик, и если вы используете htmlentities ($ string, ENT_QUOTES, 'UTF-8', true) в строке $, которую вы собираетесь вставить в XML addChild, тогда она добавит штраф, но simplexml_load_string будет разбиваться пытаясь разобрать полученный XML файл из as_xml, сгенерированного SimpleXMLElement.

Другой проблемой является список объектов, которые генерируются, возможно, долго, но пользователи могут так же легко набирать следующую & pizza; и это сломает парсер. Поскольку мне нужно обрабатывать все входные данные пользователя, я придумал следующее, но хочу знать, видите ли вы, какие случаи он потерпит неудачу.

Хотите узнать, работает ли следующее решение: замените & where в строке на & amp;. Я не смог найти случай, когда мое решение ломается, но так как это так просто, и я не видел его как решение, указанное в списке

  1. Обоснование обработки SimpleXMLElement текстовых значений в addChild и addAttribute - по этой проблеме, но не решает общую проблему
  2. Ошибка парсера XML: сущность не определена - обращение к нескольким специальным символам

Вот пример кода для моего возможного решения:

$content_amp_safe = str_replace('&','&',$content);

Вот сообщения об ошибках:

Предупреждение: simplexml_load_string(): Entity: строка 11: ошибка парсера: внутренняя ошибка Entity 'divide' not defined

Вот код, который может привести к предварительному решению проблемы:

<?php
// insert that causes the issue with the windows encoded dash, triple dot, and right quote as an example
// also issue if user enters &pizza; in the text as it is an unknown entity
$content = "I love &pizza; in the … morning  – night as well";
$content_unsafe = htmlentities($content, ENT_QUOTES, 'UTF-8', true);
//fix is to use $content_amp_safe string instead
$content_amp_safe = str_replace('&','&amp;',$content_unsafe);
$xml = new SimpleXMLElement("<?xml version='1.0' encoding='utf-8'?><Entries />");
$entry = $xml->addChild('Entry');
$entry->addChild('Content', $content);
$xml_string = $xml->asXML();
libxml_use_internal_errors(true);
$xml = simplexml_load_string($xml_string);
if ($xml === false) {
    $error_string = "Failed loading XML\n";
    foreach ( libxml_get_errors() as $error ) {
            $error_string .= "\t" . $error->message;
    }
    echo $error_string;
    ));
}
libxml_use_internal_errors(false);

?>

Короткая версия некоторых символов, которые вызывают проблемы с использованием htmlentities при вводе пользователя.

<?php 
 $table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES, 'cp1252');
 var_dump($table);
?>

Примеры символов:

€, ƒ "... † ‡ ‰ Š <Œ '" "• --~ š> œŸ ¡¢ £ ¤ ¥ | §¨ ª" ¬¯ ° ± ²³'μ¶ · ¸¹º "¼½¾¿ÀÁÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ × ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö ÷ øùúûüýþÿ & " '<>

Пример кодирования:

€, ƒ "... † ‡ ‰ Š <Œ ''" "• --~ š> œŸ ¡¢ £ ¤ ¥ | §¨ ª" ¬¯ ° ± ²³'μ¶ · ¸¹º "¼½¾¿ ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ × ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö ÷ øùúûüýþÿ & "<>

Пример нового кодирования:

& Евро; & sbquo; & fnof; & bdquo; & hellip; & Кинжал; & Dagger; & CIRC; & permil; & Scaron; & lsaquo; & OElig; & lsquo; & Rsquo; "& Rdquo; & бык; & Ndash; &— & тильдой; & торговля; & scaron; & rsaquo; & oelig; & Yuml; & NBSP; & iexcl; & цент; & фунт; & трансф; & иен; & brvbar; & раздел; & UML; & копия; & ordf; & LAQUO; & не; & застенчивы; & рег; & MACR; & град; & plusmn; & sup2; & sup3; & острый; & микро-; & пункт; & Мидот; & cedil; & ПОД1; & ordm; & RAQUO; & frac14; & frac12; & frac34; & iquest; & Agrave; & Aacute; & ACIRC; & Atilde; & AUML; & Aring; & AElig; & Ccedil; & Egrave; & Eacute; & Ecirc; & Euml; & Igrave; & Iacute; & Icirc; & Iuml; & ETH; & Ntilde; & Ograve; & Oacute; & Ocirc; & Otilde; & Ouml; & времена; & Oslash; & Ugrave; & Uacute; & Ucirc; & Uuml; & Yacute; & ШИП; & szlig; & agrave; & aacute; & ACIRC; & atilde; & AUML; & Aring; & aelig; & ccedil; & egrave; & eacute; & ecirc; & euml; & igrave; & iacute; & icirc; & iuml; & ETH; & ntilde; & ograve; & oacute; & ocirc; & otilde; & ouml; & разделим; & oslash; & ugrave; & uacute; & ucirc; & uuml; & yacute; & шипом; & yuml; & амп; " & # 039; & л; & GT;

  • 0
    Две записи вопросов и ответов, на которые вы ссылаетесь в своем вопросе, довольно хороши по данной проблеме. Мне немного интересно, вы, кажется, немного не уверены в своем заключении. Я не знаю почему. Кодировка « & » как « &amp; » в точности необходима при создании XML. Это также то, что делает SimpleXMLElement (когда вы используете доступ к свойству для изменения текстового содержимого узла элемента).
  • 0
    Спасибо @hakre. Я чувствую себя довольно хорошо о моем решении. Я был более удивлен, что никто больше не сталкивался с этой проблемой, поскольку она должна быть довольно распространенной. Хотел убедиться, что я не заново изобретал колесо или неправильно использовал функции.
Показать ещё 2 комментария
Теги:
parsing

1 ответ

1

Ваше замечание верно, что SimpleXMLElement::addChild()::addAttribute()) конвертирует (только) некоторые специальные символы в сущности.

Это должно вводить некоторые символы там дословно (особенно символ амперсанда &).

Однако вы не хотите, чтобы это было так. Чтобы преобразовать все специальные символы, вам нужно установить текстовое значение элемента XML через доступ к свойствам, например:

$entry->Content = $content;

Как вы можете видеть, $entry->addChild('Content', $content) не используется, а доступ к $entry->Content. Этот доступ к свойствам работает только в том случае, если вы вставляете один элемент Content. Если вы хотите вставить более одного в один и тот же родитель, вы должны использовать так называемую симплексную самооценку. Теперь демонстрация с помощью addChild() снова:

$entry->addChild('Content')->{0} = $content;

Пример в полном объеме:

$content = "I love &pizza; in the … morning  – night as well";

$xml = new SimpleXMLElement("<Entries />");
$entry = $xml->addChild('Entry');
$entry->Content = $content;
$entry->addChild('Content')->{0} = $content;

echo $xml->asXML();

Выход (украшенный):

<?xml version="1.0"?>
<Entries>
  <Entry>
    <Content>I love &amp;pizza; in the … morning  – night as well</Content>
    <Content>I love &amp;pizza; in the … morning  – night as well</Content>
  </Entry>
</Entries>

Надеюсь, на данный момент это не слишком запутанно.

Рядом с проблемой, которая у вас есть с амперсандом, вы можете увидеть некоторые проблемы с кодировкой символов. Для них существует одно простое правило: всякий раз, когда вы передаете строку в SimpleXMLElement, кодировка этой строки должна быть UTF-8.

Поэтому, если вы получаете данные из HTML-формы с вашего сайта, будьте осторожны, браузер отправляет такие данные, кодированные UTF-8, или повторно кодирует данные в UTF-8, прежде чем передавать их в SimpleXMLElement.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню