代码之家  ›  专栏  ›  技术社区  ›  Holstebroe

反序列化XML时忽略指定的编码

  •  7
  • Holstebroe  · 技术社区  · 14 年前

    我试图通过套接字读取从外部接口接收到的一些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头中指定的编码?

    带StreamReader的解决方案

    通过使用streamreader,我可以覆盖XML头中指定的编码。指定xmlreadersettings.ignoreprocessingstructions与不指定没有任何区别。 有趣的是,如果streamreader找到unicode字节顺序标记,它将忽略指定的编码。

    重述:

    • 如果用文本读取器初始化了XmlReader,则忽略XML头编码。
    • 如果使用StringReader,则如果存在Unicode字节顺序标记,则XmlReader将失败。
    • 如果使用streamreader,则unicode字节顺序标记将覆盖streamreader编码。
    • xmlreadersettings.ignoreprocessingstructions=true在使用文本阅读器时不会产生任何影响。

    总之,最健壮的解决方案似乎是使用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);
                    }
                }
            }
        }
    
    2 回复  |  直到 14 年前
        1
  •  3
  •   Hans Passant    14 年前

    我想我只需要使用一个使用正确编码构建的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
  •  1
  •   Jeff Yates    14 年前

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