编码CDATA元素的有效方法

时间:2009-02-13 06:02:41

标签: c# .net xml cdata streamreader

好的,我正在使用StreamReader从流中读取数据。流中的数据不是xml,它可以是任何东西。

基于输入StreamReader,我使用XmlTextWriter写入输出流。基本上,当完成所有操作时,输出流包含来自包含在父元素中的元素中的输入流的数据。

我的问题是双重的。数据以块的形式从输入流中读取,StreamReader类返回char []。如果输入流中的数据包含“]]>”它需要分成两个CDATA元素。首先,我如何搜索“]]>”在char数组中?第二,因为我正在读块,“]]>” substring可以分为两个块,所以我该如何解释呢?

我可以将char []转换为字符串,并对其进行搜索替换。这将解决我的第一个问题。在每次阅读时,我还可以检查最后一个字符是否为“]”,以便在下一次阅读时,如果前两个字符是“]>”我会开始一个新的CDATA部分。

这似乎不太有效,因为它涉及将char数组转换为字符串,这意味着花时间复制数据,并占用内存的两倍。是否有一种更有效的方式,包括速度和记忆方式吗?

3 个答案:

答案 0 :(得分:4)

根据HOWTO Avoid Being Called a Bozo When Producing XML

  

Don’t bother with CDATA sections

     

XML提供了两种转义方法   标记重要字符:   预定义实体和CDATA   部分。 CDATA部分仅限   句法糖。两种选择   句法结构没有语义   差。

     

CDATA部分很方便   正在手动编辑XML并且需要   粘贴一大块文本   包括标记重要字符   (例如,代码样本)。但是,什么时候   使用序列化器生成XML   序列化器负责转义   自动并尝试   微观管理逃避的选择   方法只为开辟了可能性   错误。
  ...
  只有<,>,&和(在属性值中)“需要转义。

只要对一小组特殊字符进行编码/转义,它就可以正常工作。

你是否必须自己处理逃避是另一回事,但肯定是一个更直接解决的问题。

然后将整批作为子文本节点附加到相关的XML元素。

答案 1 :(得分:1)

我确切知道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的任何工具)转义文本节点就可以了。

答案 2 :(得分:0)

  

第二,因为我正在阅读块,“]]&gt;” substring可以分为两个块,所以我该如何解释呢?

实际上,你必须保留队列中的最后两个字符,而不是立即吐出它们。然后当新输入进入时,将其附加到队列中并再次获取除最后两个字符之外的所有字符,对它们进行搜索和替换,然后输出。

更好:根本不打扰CDATA部分。他们只是为了方便手工创作。如果您已经在进行搜索和替换,那么您不应该只使用预定义的实体搜索并替换“&lt;”,“&gt;”和“&amp;”,并将其包含在正常情况下文本节点。由于这些是简单的单字符替换,您无需担心缓冲。

但是:如果您正在使用XmlTextWriter,就像在每个传入文本块上调用WriteString()一样简单。