Эффективный способ кодирования элементов CDATA - PullRequest
2 голосов
/ 13 февраля 2009

Хорошо, я читаю данные из потока, используя StreamReader. Данные в потоке не xml, это может быть что угодно.

На основе входного потока StreamReader я пишу в выходной поток с использованием XmlTextWriter. По сути, когда все сказано и сделано, выходной поток содержит данные из входного потока, заключенные в элемент, содержащийся в родительском элементе.

Моя проблема двоякая. Данные читаются из входного потока в чанках, а класс StreamReader возвращает char []. Если данные во входном потоке содержат «]]>», их необходимо разделить на два элемента CDATA. Во-первых, как мне найти "]]>" в массиве символов? И во-вторых, поскольку я читаю порциями, подстрока «]]>» может быть разбита на две порции, так как мне это объяснить?

Я мог бы, вероятно, преобразовать char [] в строку и выполнить поиск по ней. Это решило бы мою первую проблему. При каждом чтении я также мог проверить, был ли последний символ «]», чтобы при следующем чтении, если первые два символа были «]>», я начал новый раздел CDATA.

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

Ответы [ 3 ]

4 голосов
/ 13 февраля 2009

Согласно HOWTO Избегайте называться Bozo при создании XML :

Не беспокойтесь о секциях CDATA

XML предоставляет два способа экранирования значимые для разметки символы: предопределенные объекты и CDATA разделы. Разделы CDATA только синтаксический сахар. Две альтернативы синтаксические конструкции не имеют семантической разница.

CDATA разделы удобны, когда вы редактируете XML вручную и нужно вставить большой кусок текста, который включает значащие разметку символы (например, примеры кода). Однако когда производство XML с использованием сериализатора, сериализатор заботится о побеге автоматически и пытается Микроменеджмент выбора побега метод только открывает возможности для ошибки.
...
Только <,>, & и (в значениях атрибута) "необходимо экранировать.

Пока небольшой набор специальных символов закодирован / экранирован, он должен просто работать.

Должны ли вы справиться с побегом сами по себе, это другой вопрос, но, безусловно, гораздо более простая для решения проблема.

Затем просто добавьте весь лот как дочерний текстовый узел к соответствующему элементу XML.

1 голос
/ 13 февраля 2009

Я знаю ровно два реальных варианта использования CDATA:

Один находится в документе XHTML, содержащем скрипт:

<script type="text/javascript">
<![CDATA[
   function foo()
   {
      alert("You don't want <this> text escaped.");
   }
]]>
</script>

Другой находится в созданных вручную документах XML, где текст содержит встроенную разметку, например ::

.
<code><p>
   A typical XML element looks like this:
</p>
<p>
   <pre>
   <![CDATA[
      <sample>
         <text>
            I'm using CDATA here so that I don't have to manually escape
            all of the special characters in this example.
         </text>
      </sample>
   ]]>
   

Во всех других случаях, просто позволяя DOM (или XmlWriter, или любому другому инструменту, который вы используете для создания XML) экранировать текстовые узлы, работает очень хорошо.

0 голосов
/ 13 февраля 2009

секунда, потому что я читаю чанками, подстрока "]]>" может быть разбита на две чанки, так как мне это объяснить?

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

Лучше: вообще не беспокойтесь о разделе CDATA. Они есть только для удобства ручной работы. Если вы уже выполняете поиск и замену, нет причин, по которым вы не должны просто искать и заменять ‘<’, ‘>’ и ‘&’ с их предопределенными объектами и включать их в обычный текстовый узел. Поскольку это простые односимвольные замены, вам не нужно беспокоиться о буферизации.

Но: если вы используете XmlTextWriter, как вы говорите, это так же просто, как вызывать WriteString () для каждого фрагмента входящего текста.

...