6

.Net 3.5 内のさまざまな XML 実装の間に矛盾があることを発見したようで、名目上正しいものを見つけるのに苦労しています。

この問題は、実際にはかなり簡単に再現できます。

  1. 「\t」文字を含むテキスト要素を持つ単純な xml ドキュメントを作成し、「\t」文字を含む属性を指定します。

    var xmlDoc = new XmlDocument { PreserveWhitespace = false, };
    xmlDoc.LoadXml("<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>");
    xmlDoc.Save(@"d:\TabTest.xml");
    

    注意: これは、XmlDocument 自体が属性値の '\t' 文字に非常に満足していることを意味します。

  2. 新しい XmlTextReader を使用してドキュメントを読み込みます。

    var rawFile = XmlReader.Create(@"D:\TabTest.xml");
    var rawDoc = new XmlDocument();
    rawDoc.Load(rawFile);
    
  3. XmlReader.Create を使用してドキュメントを読み込みます。

    var rawFile2 = new XmlTextReader(@"D:\TabTest.xml");
    var rawDoc2 = new XmlDocument();
    rawDoc2.Load(rawFile2);
    
  4. デバッガーでドキュメントを比較します。

    (rawDoc).InnerXml   "<test><text attrib=\"Tab' 'space' '\">Tab'\t'space' '</text></test>"   string
    (rawDoc2).InnerXml  "<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>"  string
    

新しい XmlTextReader を使用して読み取られたドキュメントは、期待どおりでした。テキスト値と属性値の両方に「\t」がありました。しかし、XmlReader.Create で読み取ったドキュメントを見ると、属性値の「\t」文字が文字に変換されていることがわかります' '

なんと……!! :-)

ちょっとした Google 検索の結果、'\t' を ' ' としてエンコードできることがわかりました。- XML の例で '\t' の代わりにこれを使用すると、両方のリーダーが期待どおりに動作します。

現在、Altova XmlSpy およびその他のさまざまな XML リーダーは、属性値の '\t' 文字に完全に満足しているようです。私の質問は、これを処理する正しい方法は何ですか?

XmlReader.Create のような属性値でエンコードされた '\t' 文字を使用して XML ファイルを作成する必要がありますか、それとも他の XML ツールが正しく、'\t' 文字は有効であり、XmlReader.Create は壊れていますか?

この問題を修正/回避するには、どの方法を使用すればよいですか?

4

4 に答える 4

2

おそらく、属性値の正規化と関係があります。CDATA属性の場合、属性値の改行とタブをスペースで置き換えるには、XMLパーサーが必要です。ただし、これらが文字参照としてエスケープされた形式で記述されている場合を除きます。

于 2012-09-04T14:18:53.790 に答える
2

@all: すべての回答とコメントに感謝します。

Justin と Michael Kay は正しく、ホワイト スペースは W3C XML 仕様に従ってエンコードする必要があるように思われます。問題は、かなりの数の MS 実装がこの要件を順守していないことです。

私の場合、XML 仕様は別として、私が本当に望んでいるのは、属性値が正しく永続化されることです。つまり、保存される値は、読み取られた値とまったく同じでなければなりません。

これに対する答えは、最初に XML ファイルを保存するときに XmlWriter.Create メソッドを使用して作成された XmlWriter の使用を強制することです。

Dataset と XmlDocument はどちらも保存/書き込みメカニズムを提供しますが、既定の形式で使用した場合、どちらも属性の空白を正しくエンコードしません。ただし、手動で作成した XmlWriter の使用を強制すると、正しいエンコーディングが適用され、ファイルに書き込まれます。

したがって、元のファイル保存コードは次のようになります。

var xmlDoc = new XmlDocument { PreserveWhitespace = false, };
xmlDoc.LoadXml("<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>");

using (var xmlWriter = XmlWriter.Create(@"d:\TabTest.Encoded.xml"))
{
    xmlDoc.Save(xmlWriter);
}

次に、このライターは、XmlReader.Create リーダーが属性値を変更せずに読み取れるように、対称的な方法で空白を正しくエンコードします。

ここで注意すべきもう 1 つの点は、このソリューションはコードのエンコーディングを完全にカプセル化するということです。これは、リーダーとライターが読み取りと書き込みで透過的にエンコードとデコードを実行するためです。

于 2012-09-05T09:33:58.680 に答える
1

一見、W3C 勧告に準拠してXmlTextReaderないように見えます。特に、属性値の正規化に関する推奨事項のセクションを参照してください。

空白文字 (#x20、#xD、#xA、#x9) の場合、正規化された値に空白文字 (#x20) を追加します。

したがって、予期していなかった動作 (タブの代わりにスペースが表示される) は、実際には推奨される正しい動作です。

なぜXmlTextReaderこのように振る舞うかはわかりませんが(ドキュメントには何もありません)、正しい回避策をすでに特定しているようです-&#x9;代わりに属性をエンコードしてください。この場合、正規化された文字列にはタブ文字自体が含まれます。

于 2012-09-04T15:12:49.127 に答える
1

XmlReaderSettings.ComformanceLevelを確認してください。特に、この説明:

Create メソッドによって作成された XmlReader オブジェクトは、既定で XmlTextReader クラスよりも準拠していることに注意してください。以下は、XmlTextReader では有効になっていないが、Create メソッドによって作成されたリーダーで既定で使用できる適合性の向上です。

于 2012-09-04T15:18:45.050 に答える