2010-09-27 1 views
24

Я искал stackoverflow по этой проблеме и нашел несколько тем, но я чувствую, что на самом деле нет надежного ответа на меня.Ошибка XML-парсера: объект не определен

У меня есть форма, которую пользователи представляют, а значение поля хранится в файле XML. XML настроен на кодирование с помощью UTF-8.

Время от времени пользователь будет копировать/вставлять текст откуда-то, и тогда я получаю «сущность, не определенную ошибку».

Я понимаю, что XML поддерживает только несколько сущностей, и все, что за ним не распознается, - следовательно, ошибка парсера.

Из того, что я понимаю, что есть несколько вариантов, которые я видел:

  1. я могу найти и заменить все   и поменять их местами с   или фактическим местом.
  2. Я могу разместить код в разделе CDATA.
  3. Я могу включить эти объекты в XML-файл.

Что я делаю с XML-файлом, так это то, что пользователь может вводить содержимое в форму, он хранится в XML-файле, и этот контент затем отображается как XHTML на веб-странице (анализируется SimpleXML).

Из трех вариантов или любых других вариантов (-ов), о которых я не знаю, что является лучшим способом справиться с этими сущностями?

Спасибо, Райан

UPDATE

Я хочу поблагодарить всех за большую обратную связь. Я фактически определил, что вызвало ошибки моего объекта. Все предложения заставили меня глубже изучить это!

Некоторые текстовые поля, в которых простые текстовые поля, но мои текстовые поля были расширены с помощью TinyMCE. Оказывается, при внимательном рассмотрении, что предупреждения PHP всегда ссылаются на данные из расширенных текстовых областей TinyMCE. Позже я заметил на ПК, что все персонажи были вывезены (потому что они не могли их прочитать), но на MAC вы могли видеть квадраты квадратов, ссылающиеся на номер юникода этого символа. Причина, по которой он проявился в квадратах на MAC, заключается в том, что я использовал utf8_encode для кодирования данных, которые не были в UTF, чтобы предотвратить другие ошибки синтаксического анализа (что также связано с TinyMCE).

Решение все это было довольно просто:

Я добавил эту линию entity_encoding : "utf-8" в моей tinyMCE.init. Теперь все персонажи появляются так, как они предполагают.

Я думаю, что единственное, что я не понимаю, - это то, почему персонажи все еще появляются, когда помещаются в текстовые поля, потому что ничто не преобразует их в UTF, но с TinyMCE это была проблема.

+0

Некоторые важные части вашего вопроса невидимы, потому что они получили разобран как разметка. Пожалуйста, объедините эти биты с backquotes (''). – LarsH

+0

@LarsH: Хм, я ничего не вижу в источнике вопроса, который бы нуждался в этом. – Tomalak

+0

@Tomalak: «1. Я могу найти и заменить все * ?? * и поменять их на * ?? * или фактическое пространство». Конечно, мне кажется, что там что-то не хватает. – LarsH

ответ

13

Вы можете анализировать HTML-текст и повторно его использовать с соответствующими числовыми объектами (например:   ). В любом случае - просто с использованием неуспешный пользовательский ввод - плохая идея.

Все числовые лиц разрешены в XML, только названные те известные из HTML не работают (за исключением &, ", <, >, ').

Большую часть времени, хотя, вы можете просто написать фактический характер (öö) в файл XML, так что нет необходимости использовать ссылку на сущность на всех. Если вы используете DOM API для управления вашим XML (и вы должны!), Это ваша самая безопасная ставка.

Наконец-то (это ленивое решение для разработчиков) вы можете создать разбитый XML-файл (т. Е. Неправильно сформированный, с ошибками сущности) и всего pass it through tidy для необходимых исправлений. Это может работать или может закончиться в зависимости от , так как сломал все это. По моему опыту, аккуратность довольно умна, и позволяет вам уйти с большим успехом.

+0

«Вы можете анализировать текст с помощью HTML и повторно использовать его с соответствующими числовыми объектами» - означает ли это, что вы всегда можете хранить числовые объекты над объектами HTML-текста? -Ryan – NightHawk

+0

@Ryan: Да, числовые объекты разрешены (и распознаются) как XML, так и HTML. – Tomalak

+0

@Tomalak Это означает, что я должен был знать все сущности по имени и их числовому объекту заранее, верно? Это будет чрезвычайно интенсивная обработка, если я добавлю их всех туда? -Ryan – NightHawk

1

Если вы хотите, чтобы преобразовать все символы, это может помочь вам (я это написал некоторое время назад):

http://www.lautr.com/convert-all-applicable-characters-to-numeric-entities-for-use-in-xml

function _convertAlphaEntitysToNumericEntitys($entity) { 
    return '&#'.ord(html_entity_decode($entity[0])).';'; 
} 

$content = preg_replace_callback(
    '/&([\w\d]+);/i', 
    '_convertAlphaEntitysToNumericEntitys', 
    $content); 

function _convertAsciOver127toNumericEntitys($entity) { 
    if(($asciCode = ord($entity[0])) > 127) 
    return '&#'.$asciCode.';'; 
    else 
    return $entity[0]; 
} 

$content = preg_replace_callback(
    '/[^\w\d ]/i', 
    '_convertAsciOver127toNumericEntitys', $content); 
+0

хорошо, если вы примените «$ content = preg_replace_callback ('/ & ([\ w \ d] +);/i', '_ convertAlphaEntitysToNumericEntitys', $ content); весь объект HTML (  и еще что) будет изменен на числовые объекты. После этого примените «$ content = preg_replace_callback ('/ [^ \ w \ d]/i', '_ convertAsciOver127toNumericEntitys'), $ content);" и каждый символ выше 127 (который не обрабатывается htmlspecialchars) преобразуется в числовой объект, если я его неправильно понимаю, можете ли вы привести примерный фрагмент ввода? – Hannes

+0

Извините, я неправильно понял, что сделал ваш код. Удаление моего предыдущего комментария. – LarsH

4

1 . I can find and replace all [   ?] and swap them out with [   ?] or an actual space.

Это надежный метод, но он требует иметь таблицу всех объектов HTML (я предполагаю, что вставленный ввод поступает из HTML) и проанализировать вложенный текст для ссылок на сущности.

2 . I can place the code in question within a CDATA section.

Другими словами отключить разбор по всему разделу? Тогда вам придется разбирать его по-другому. Может работать.

3 . I can include these entities within the XML file.

Вы имеете в виду включать определения сущности? Я думаю, что это простой и надежный способ, если вы не возражаете, чтобы XML-файл был немного больше. У вас может быть «включенный» файл (найти его в Интернете), который является внешним объектом, с которым вы ссылаетесь в верхней части основного файла XML.

Единственным недостатком является то, что используемый вами XML-анализатор должен обрабатывать внешние объекты (которые не все парсеры должны выполнять). И он должен правильно разрешить (возможно относительный) URL-адрес внешнего объекта к чему-то доступному. Это не так уж плохо, но это может увеличить ограничения на ваши инструменты обработки.

4. Вы можете запретить не-XML в вставленном контенте. Помимо всего прочего, это будет запрещать ссылки на сущности, которые не предопределены в XML (5, упомянутые Томалаком) или определенные в самом содержимом. Однако это может нарушить требования приложения, если пользователи должны иметь возможность вставлять в него HTML.

5. Вы можете анализировать вставленный контент как HTML в дерево DOM, установив someDiv.innerHTML = thePastedContent; Другими словами, создайте div где-нибудь (возможно, display = none, за исключением отладки). Скажем, у вас есть переменная javascript myDiv, которая содержит этот элемент div, и другую переменную myField, которая содержит элемент, который является вашим текстовым полем ввода. Тогда в JavaScript вы

myDiv.innerHTML = myField.value; 

который принимает неанализируемый текст из MyField, разбирает его в DOM дерево HTML и прилипает его в myDiv как содержание HTML.

Затем вы должны использовать некоторый браузерный метод для сериализации (= «де-парсинга») дерева DOM в XML. См. Например, this question. Затем вы отправляете результат на сервер в виде XML.

Если вы хотите сделать это исправление в браузере или на сервере (как предлагал @Hannes), это будет зависеть от размера данных, от того, насколько быстро должен быть ответ, насколько велик ваш сервер и есть ли у вас заботиться о том, чтобы хакеры отправляли не-правильно сформированный XML.

+0

@Tomalak - почему бы ö стать & ouml ;? Когда текст помещается в innerhtml, не будет ли он разбираться в dom как один символ o-умлаут? – LarsH

+0

1. Возможно, слишком много накладных расходов, не так ли? 2. С другой стороны, это кажется контрпродуктивным, поэтому я собираюсь устранить этот вариант. 3. Кроме того, файл больше, есть ли другие недостатки? Если нет, я бы сказал, что это путь. 4. Да, это нарушит требования. 5. Я не понимаю этого решения - можете ли вы предоставить более подробную информацию? -Ryan – NightHawk

+0

@Ryan, я отредактирую свой ответ, чтобы добавить подробную информацию о 3 и 5. – LarsH

19

Я согласен с тем, что это проблема с кодировкой. В PHP это то, как я решил эту проблему:

  1. Прежде чем перейти HTML-фрагмент в SimpleXMLElement конструктору я декодированного его с помощью html_entity_decode.

  2. Затем дополнительно закодировано с использованием utf8_encode().

$headerDoc = '<temp>' . utf8_encode(html_entity_decode($headerFragment)) . '</temp>'; 
$xmlHeader = new SimpleXMLElement($headerDoc); 

Теперь приведенный выше код не пролить ошибки неопределенного объекта.

+7

Возможно, вам удастся избежать использования 'utf8_encode', если вы дадите' 'UTF-8' '[' html_entity_decode'] (http://php.net/manual/en/function.html-entity-decode. php) в качестве третьего параметра, например 'html_entity_decode ($ headerFragment, null," UTF-8 ")' –

0

Этот вопрос является общей проблемой для любого языка, который анализирует XML или JSON (так, в основном, каждый язык).

Приведенные выше ответы на PHP, но решение Perl будет столь же легко, как ...

my $excluderegex = 
    '^\n\x20-\x20' . # Don't Encode Spaces 
     '\x30-\x39' . # Don't Encode Numbers 
     '\x41-\x5a' . # Don't Encode Capitalized Letters 
     '\x61-\x7a' ; # Don't Encode Lowercase Letters 

    # in case anything is already encoded 
$value = HTML::Entities::decode_entities($value); 

    # encode properly to numeric 
$value = HTML::Entities::encode_numeric($value, $excluderegex); 
Смежные вопросы