2

OK、StreamReader を使用してストリームからデータを読み取っています。ストリーム内のデータは xml ではなく、何でもかまいません。

入力 StreamReader に基づいて、XmlTextWriter を使用して出力ストリームに書き込みます。基本的に、出力ストリームには、親要素に含まれる要素にラップされた入力ストリームからのデータが含まれます。

私の問題は 2 つあります。データは入力ストリームからチャンクで読み取られ、StreamReader クラスは char[] を返します。入力ストリームのデータに「]]>」が含まれている場合、2 つの CDATA 要素に分割する必要があります。まず、char 配列で "]]>" を検索するにはどうすればよいですか? 次に、チャンクで読み取っているため、"]]>" 部分文字列が 2 つのチャンクに分割される可能性があります。

おそらく、char[] を文字列に変換し、検索置換を行うことができます。それは私の最初の問題を解決するでしょう。読み取るたびに、最後の文字が「]」であるかどうかを確認することもできたので、次の読み取りで最初の 2 文字が「]>」であれば、新しい CDATA セクションを開始します。

これは、char 配列を文字列に変換する必要があるため、ほとんど効率的ではありません。つまり、データのコピーに時間がかかり、2 倍のメモリを消費します。スピードに関してもメモリに関しても、より効率的な方法はありますか?

4

3 に答える 3

4

HOWTOによると、 XML を生成するときにボゾと呼ばれることを回避します。

CDATA セクションを気にしないでください

XML には、マークアップで重要な文字をエスケープする方法が 2 つあります。定義済みのエンティティと CDATA セクションです。CDATA セクションはシンタックス シュガーにすぎません。2 つの代替構文構造には、意味上の違いはありません。

CDATA セクションは、XML を手動で編集していて、マークアップで重要な文字 (コード サンプルなど) を含む大量のテキストを貼り付ける必要がある場合に便利です。ただし、シリアライザーを使用して XML を生成する場合、シリアライザーは自動的にエスケープを処理し、エスケープ方法の選択を細かく管理しようとすると、バグの可能性が広がるだけです。
...
<、>、& および (属性値内の) " だけがエスケープする必要があります。

特殊文字の小さなセットがエンコード/エスケープされている限り、機能するはずです。

エスケープを自分で処理する必要があるかどうかは別の問題ですが、確かにはるかに簡単に解決できる問題です。

次に、すべてを子テキスト ノードとして関連する XML 要素に追加します。

于 2009-02-13T14:37:06.867 に答える
1

CDATA の実際の使用例を 2 つだけ知っています。

1 つは、スクリプトを含む XHTML ドキュメントにあります。

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

もう 1 つは、テキストに埋め込みマークアップが含まれる手書きの 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

第二に、私はチャンクで読んでいるので、"]]>" 部分文字列は 2 つのチャンクに分割される可能性があります。

実際、最後の 2 文字をすぐに吐き出すのではなく、キューに入れておく必要があります。次に、新しい入力が入ってくると、それをキューに追加し、最後の 2 文字を除くすべての文字を再度取得し、それらを検索して置換し、出力します。

ベター: CDATA セクションをまったく気にしないでください。これらは、手書きの便宜のためにのみ存在します。すでに検索と置換を行っている場合、'<'、'>'、'&' だけを検索して置換しない理由はありません。事前定義されたエンティティを使用し、それらを通常のテキスト ノードに含めます。これらは単純な 1 文字の置換であるため、バッファリングについて心配する必要はありません。

しかし、あなたが言うように XmlTextWriter を使用している場合、受信テキストの各チャンクに対して WriteString() を呼び出すのと同じくらい簡単です。

于 2009-02-13T10:21:38.273 に答える