C#のストリームに対してXPathNavigatorを安全に作成するにはどうすればよいですか?
質問
入力としてストリームを指定した場合、XMLデータソースに対してXPathNavigatorを安全に作成するにはどうすればよいですか
XMLデータソース:
- 削除する必要がある無効な16進文字が含まれている可能性があります。
- 文書の宣言されたエンコーディングと一致しない文字が含まれている場合があります。
例として、クラウド内の一部のXMLデータソースには utf-8 のエンコードが宣言されていますが、実際のエンコードは windows-1252 またはです。 ISO 8859-1 。ストリームに対してXmlReaderを作成するときに無効な文字例外がスローされる可能性があります。
StreamReader.CurrentEncoding プロパティドキュメントから:"現在のリーダーで使用されている現在の文字エンコーディング。読み取りメソッドの最初の呼び出しまでエンコードの自動検出は行われないため、StreamReaderの読み取りメソッドの最初の呼び出しの後に値が異なる場合があります。これは、最初の読み取り後にCurrentEncodingをチェックできることを示しているようですが、XMLデータをストリームに書き出す必要があるときに、このエンコードを保存し続けていますか?
無効な文字の問題のエンコードを適切に処理するXMLデータソースに対してXPathNavigator / IXPathNavigableインスタンスを安全に作成するためのベストプラクティスを見つけることを望んでいます(C#が望ましい)。
解決
いくつかのXMLフラグメントが間違ったエンコーディングを使用してCRMシステムにインポートされたときに、同様の問題が発生しました(XMLフラグメントとともにエンコーディングが保存されていませんでした)。
ループで、リストの現在のエンコーディングを使用してラッパーストリームを作成しました。エンコーディングは、DecoderExceptionFallbackおよびEncoderExceptionFallbackオプションを使用して構築されました(@Dougが言及したとおり)。処理中にDecoderFallbackExceptionがスローされた場合、元のストリームはリセットされ、次に最も可能性の高いエンコーディングが使用されます。
エンコーディングリストは、UTF-8、Windows-1252、GB-2312、US-ASCIIなどです。リストの最後から落ちた場合、ストリームは本当に悪く、拒否/無視/などされました。
編集:
簡単なサンプルと基本的なテストファイルを作成しました(ソースこちら)。コードには、両方が同じバイトセットに一致するコードページを選択するためのヒューリスティックがありません。そのため、Windows-1252ファイルはGB2312として検出される場合があります。 / p>
他のヒント
DecoderFallback クラスを使用できます(およびいくつかの関連クラス)をスキップするか、別の処理(新しいエンコーディングで再起動しますか?)で不良文字を処理します。
XmlTextReaderまたは類似のものを使用する場合、リーダー自体がxmlファイルで宣言されたエンコーディングを判断します。