7

アプリケーションに次の XML 解析コードがあります。

    public static XElement Parse(string xml, string xsdFilename)
    {
        var readerSettings = new XmlReaderSettings
        {
            ValidationType = ValidationType.Schema,
            Schemas = new XmlSchemaSet()
        };
        readerSettings.Schemas.Add(null, xsdFilename);
        readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        readerSettings.ValidationEventHandler +=
            (o, e) => { throw new Exception("The provided XML does not validate against the request's schema."); };

        var readerContext = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.UTF8);

        return XElement.Load(XmlReader.Create(new StringReader(xml), readerSettings, readerContext));
    }

カスタム逆シリアル化のために、WCF サービスに送信された文字列を XML ドキュメントに解析するために使用しています。

ファイルを読み込んでネットワーク経由で送信すると(リクエスト)、正常に動作します。BOM が送信されていないことを確認しました。私のリクエスト ハンドラでは、レスポンス オブジェクトをシリアル化し、文字列として送り返しています。シリアライゼーション プロセスでは、文字列の前に UTF-8 BOM が追加されるため、応答を解析するときに同じコードが壊れます。

System.Xml.XmlException : Data at the root level is invalid. Line 1, position 1.

この 1 時間ほどで行った調査では、XmlReader は BOM を尊重する必要があるようです。文字列の先頭から BOM を手動で削除すると、応答 xml は正常に解析されます。

明らかな何か、または少なくとも陰湿な何かが欠けていますか?

編集:応答を返すために使用しているシリアル化コードは次のとおりです。

private static string SerializeResponse(Response response)
{
    var output = new MemoryStream();
    var writer = XmlWriter.Create(output);
    new XmlSerializer(typeof(Response)).Serialize(writer, response);
    var bytes = output.ToArray();
    var responseXml = Encoding.UTF8.GetString(bytes);
    return responseXml;
}

BOM が正しく含まれていない xml の問題である場合は、次のように切り替えます。

var responseXml = new UTF8Encoding(false).GetString(bytes);

しかし、私の調査では、BOM が実際の XML 文字列で違法であることはまったく明らかではありませんでした。たとえば、c# Byte Array から xml エンコーディングを検出しますか? を参照してください。

4

5 に答える 5

9

私のリクエスト ハンドラでは、レスポンス オブジェクトをシリアル化し、文字列として送り返しています。シリアライゼーション プロセスでは、文字列の前に UTF-8 BOM が追加されるため、応答を解析するときに同じコードが壊れます。

そのため、シリアライゼーション プロセスの一部として BOM が追加されないようにする必要があります。残念ながら、シリアル化ロジックが何であるかを提供していません。

あなたがすべきことは、 UTF8Encoding(bool)コンストラクターを介して作成されたUTF8Encodingインスタンスを提供して、BOM の生成を無効にし、このインスタンスを、中間文字列を生成している使用中のメソッドに渡すことです。Encoding

于 2010-06-23T17:57:07.503 に答える
6

xml 文字列に BOM を含めることはできません (!)。BOM は、UTF-8 でエンコードされたバイト データ (ストリームなど) でのみ許可されます。これは、文字列表現がエンコードされておらず、すでに Unicode 文字のシーケンスであるためです。

したがって、文字列を間違ってロードしたようです。これは、残念ながら提供していないコードにあります。

編集:

シリアライゼーションコードを投稿していただきありがとうございます。

データを MemoryStream に書き込むのではなく、ToString で文字列に変換できる StringWriter に書き込む必要があります。これにより、バイト表現を通過することが回避されるため、高速になるだけでなく、そのような問題も回避されます。

このようなもの:

private static string SerializeResponse(Response response)
{
    var output = new StringWriter();
    var writer = XmlWriter.Create(output);
    new XmlSerializer(typeof(Response)).Serialize(writer, response);
    return output.ToString();
}
于 2010-06-23T17:49:40.810 に答える
0

そもそも BOM を文字列に含めるべきではありません。
BOM は、未加工のバイト配列のエンコーディングを検出するために使用されます。彼らは実際の文字列にいるビジネスを持っていません。

文字列は何から来ていますか?
あなたはおそらく間違ったエンコーディングでそれを読んでいます。

于 2010-06-23T17:49:54.737 に答える
0

C# の文字列は UTF-16 としてエンコードされるため、BOM は正しくありません。原則として、常に XML をバイト配列にエンコードし、バイト配列からデコードします。

于 2010-06-23T17:50:47.620 に答える