2

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

基于输入 StreamReader,我正在使用 XmlTextWriter 写入输出流。基本上,当一切都说完了,输出流包含来自输​​入流的数据,这些数据包装在父元素中包含的元素中。

我的问题是双重的。数据以块的形式从输入流中读取,StreamReader 类返回 char[]。如果输入流中的数据包含“]]>”,则需要将其拆分为两个 CDATA 元素。首先,如何在 char 数组中搜索“]]>”?其次,因为我是分块阅读,所以“]]>”子字符串可以分成两个块,那么我该如何解释呢?

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

这看起来几乎没有效率,因为它涉及将 char 数组转换为字符串,这意味着要花费时间来复制数据,并占用两倍的内存。有没有更有效的方法,无论是在速度方面还是在内存方面?

4

3 回答 3

4

根据HOWTO 避免在生产 XML 时被称为 Bozo

不要打扰 CDATA 部分

XML 提供了两种转义标记有效字符的方法:预定义实体和 CDATA 部分。CDATA 部分只是语法糖。这两种替代句法结构没有语义差异。

当您手动编辑 XML 并且需要粘贴包含标记有效字符的大量文本(例如代码示例)时,CDATA 部分很方便。但是,当使用序列化程序生成 XML 时,序列化程序会自动处理转义,并且尝试对转义方法的选择进行微观管理只会带来错误的可能性。
...
只有 <、>、& 和(在属性值中)" 需要转义。

只要对一小部分特殊字符进行编码/转义,它就应该可以工作。

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

然后只需将全部作为子文本节点附加到相关的 XML 元素。

于 2009-02-13T14:37:06.867 回答
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 的任何工具)转义文本节点就可以了。

于 2009-02-13T20:15:59.717 回答
0

其次,因为我正在分块阅读,所以“]]>”子字符串可以分成两个块,那么我该如何解释呢?

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

更好:根本不用担心 CDATA 部分。它们只是为了方便手工创作而存在。如果您已经在进行搜索和替换,那么您没有理由不只搜索和替换 '<'、'>' 和 '&' 及其预定义的实体,并将这些实体包含在普通的 Text 节点中。由于这些是简单的单字符替换,因此您无需担心缓冲。

但是:如果您按照您所说的那样使用 XmlTextWriter,那么它就像为每个传入文本块调用 WriteString() 一样简单。

于 2009-02-13T10:21:38.273 回答