Эффективный способ кодирования элементов CDATA
-
23-08-2019 - |
Вопрос
Хорошо, я читаю данные из потока с помощью StreamReader.Данные внутри потока не являются XML, это может быть что угодно.
На основе входного StreamReader я пишу в выходной поток с помощью XmlTextWriter.По сути, когда все сказано и сделано, выходной поток содержит данные из входного потока, обернутые элементом, содержащимся в родительском элементе.
Моя проблема двоякая.Данные считываются из входного потока порциями, а класс StreamReader возвращает char[].Если данные во входном потоке содержат «]]>», их необходимо разделить на два элемента CDATA.Во-первых, как мне найти «]]>» в массиве символов?И во-вторых, поскольку я читаю фрагментами, подстроку «]]>» можно разделить на два фрагмента, как мне это учесть?
Вероятно, я мог бы преобразовать char[] в строку и выполнить поиск по ней.Это решило бы мою первую проблему.При каждом чтении я мог также проверять, был ли последний символ «]», чтобы при следующем чтении, если первые два символа были «]>», я начинал новый раздел CDATA.
Это вряд ли кажется эффективным, поскольку включает в себя преобразование массива символов в строку, что означает трату времени на копирование данных и потребление вдвое больше памяти.Есть ли более эффективный способ, как по скорости, так и по памяти?
Решение
во-вторых, поскольку я читаю фрагментами, подстроку «]]>» можно разделить на два фрагмента, как мне это учесть?
Действительно, вам придется оставить два последних символа в очереди вместо того, чтобы немедленно их выплеснуть.Затем, когда поступает новый ввод, добавьте его в очередь и снова возьмите все символы, кроме двух последних, выполните поиск и замену по ним и выведите.
Лучше:вообще не беспокойтесь о разделе CDATA.Они нужны только для удобства ручного написания.Если вы уже выполняете поиск и замену, нет причин, по которым вам не следует просто искать и заменять «<», «>» и «&» их предопределенными объектами и включать их в обычный текстовый узел.Поскольку это простые односимвольные замены, вам не нужно беспокоиться о буферизации.
Но:если вы используете XmlTextWriter, как вы говорите, это так же просто, как вызвать WriteString() для каждого фрагмента входящего текста.
Другие советы
В соответствии с КАК избежать того, чтобы вас называли болваном при создании XML:
Не беспокойтесь о разделах CDATA
XML предоставляет два способа избежать сознательных символов.Предопределенные сущности и разделы CDATA.Срезы CDATA представляют собой только синтаксический сахар.Две альтернативные синтаксические конструкции не имеют семантической разницы.
Разделы CDATA удобны, когда вы редактируете XML вручную, и вам нужно вставить большую часть текста, который включает в себя символические символы (например.примеры кода).Однако при производстве XML с использованием сериализатора сериализатор позаботится об автоматическом сбеге и пытается микроуправлять выбор метода сбега, который только открывает возможности для ошибок.
...
Только <, >, & и (в значениях атрибутов) " нуждаются в экранировании.
Пока небольшой набор специальных символов закодирован/экранирован, он должен просто работать.
Другое дело, придется ли вам самим справляться с побегом, но, безусловно, это гораздо более простая для решения проблема.
Затем просто добавьте все это в качестве дочернего текстового узла к соответствующему элементу XML.
Я знаю ровно два реальных варианта использования CDATA:
Один из них находится в документе XHTML, содержащем скрипт:
<script type="text/javascript">
<![CDATA[
function foo()
{
alert("You don't want <this> text escaped.");
}
]]>
</script>
Другой — в XML-документах, созданных вручную, где текст содержит встроенную разметку, например:
<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>
]]>
</pre>
</p>
Во всех остальных случаях просто позволить DOM (или XmlWriter, или любому другому инструменту, который вы используете для создания XML) избежать текстовых узлов, работает нормально.