【问题标题】:Ignoring specified encoding when deserializing XML反序列化 XML 时忽略指定的编码
【发布时间】:2010-10-27 14:14:16
【问题描述】:

我正在尝试通过套接字读取从外部接口接收到的一些 XML。 问题是在 XML 标头中指定的编码错误(它说 iso-8859-1,但它是 utf-16BE)。据记载,编码是utf-16BE,但显然他们忘了设置正确的编码。

要在反序列化时忽略编码,我使用这样的 StringReader:

    private static T DeserializeXmlData<T>(byte[] xmlData)
    {
        var xmlString = Encoding.BigEndianUnicode.GetString(xmlData);
        using (var reader = new StringReader(xmlString))
        {
            reader.ReadLine(); // Eat header line
            using (var xmlReader = XmlReader.Create(reader))
            {
                var serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(xmlReader);
            }
        }
    }

上面的内容实际上运行良好,但我不喜欢通过调用 ReadLine 跳过标题行的部分。 有没有更简单的方法来绕过 XML-header 中指定的编码?

使用 StreamReader 的解决方案

通过使用 StreamReader,我可以覆盖 XML 标头中指定的编码。是否指定 XmlReaderSettings.IgnoreProcessingInstructions 没有任何区别。 有趣的是,如果 StreamReader 找到一个 unicode 字节顺序标记,它会忽略指定的编码。

回顾一下:

  • 如果 XmlReader 使用 TextReader 初始化,则忽略 XML 标头编码。
  • 如果使用 StringReader,如果存在 unicode 字节顺序标记,则 XmlReader 会失败。
  • 如果使用 StreamReader,则 unicode 字节顺序标记会覆盖 StreamReader 编码。
  • XmlReaderSettings.IgnoreProcessingInstructions = true 在使用 TextReader 时没有任何区别。

总之,最强大的解决方案似乎是使用 StreamReader,因为它使用字节顺序标记(如果存在)。

    private static T DeserializeXmlData<T>(byte[] xmlData)
    {
        using (var xmlDataStream = new MemoryStream(xmlData))
        {
            using (var reader = new StreamReader(xmlDataStream, Encoding.BigEndianUnicode))
            {
                using (var xmlReader = XmlReader.Create(reader))
                {
                    var serializer = new XmlSerializer(typeof (T));
                    return (T) serializer.Deserialize(xmlReader);
                }
            }
        }
    }

【问题讨论】:

    标签: .net xml xmlserializer stringreader


    【解决方案1】:

    我想我只是使用一个 StreamReader,用正确的编码构造并将它传递给 XmlReader.Create(TextStream) 方法:

     using (var sr = new StreamReader(@"c:\temp\bad.xml", Encoding.BigEndianUnicode)) {
         using (var xr = XmlReader.Create(sr, new XmlReaderSettings())) {
             // etc...
         }
     }
    

    【讨论】:

      【解决方案2】:

      如果没有其他相关的处理指令,你可以通过设置XmlReaderSettings.IgnoreProcessingInstructions忽略它们。

      【讨论】:

      • 太棒了!那么我将如何指定“真实”编码? (即使 IgnoreProcessingInstructions 设置为 true,基于 StringReader 的 XmlReader 也会引发异常)。
      猜你喜欢
      • 2012-10-19
      • 1970-01-01
      • 2013-04-07
      • 2013-08-17
      • 2012-09-17
      • 2021-02-17
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多