我的应用程序中有以下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.

在我在最后一个小时左右做的研究中,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;
}

如果仅仅是XML错误包含BOM的问题,那么我将切换到

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

但是我的研究根本不清楚BOM在实际XML字符串中是非法的。参见例如 C#从字节数组中检测XML编码?

有帮助吗?

解决方案

XML字符串不得包含BOM,仅在用UTF-8编码的字节数据(例如流)中允许BOM。这是因为字符串表示未编码,而是一系列Unicode字符。

因此,似乎您将字符串加载错误,这是您不幸的代码中未提供的代码。

编辑:

感谢您发布序列化代码。

您不应将数据写入MemoryStream,而应将数据写给StringWriter,然后可以将其转换为带有ToString的字符串。由于这避免了通过字节表示,它不仅更快,而且避免了此类问题。

这样的事情:

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();
}

其他提示

在我的请求处理程序中,我将响应对象序列化并将其作为字符串发送回。序列化过程将UTF-8 BOM添加到字符串的正面,这会导致相同的代码在解析响应时断开。

因此,您想防止将BOM作为序列化过程的一部分添加。不幸的是,您没有提供序列化逻辑。

您应该做的是提供 utf8encoding 通过 utf8encoding(bool) 禁用生成BOM的构造函数,并通过 Encoding 实例要用于生成中间字符串的任何方法。

BOM首先不应在弦上。
BOM用于检测原始字节阵列的编码;他们没有生意在实际的字符串中。

字符串来自什么?
您可能会用错误的编码阅读它。

C#中的字符串编码为UTF-16,因此BOM是错误的。通常,始终将XML编码为字节数组并从字节数组解码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top