2010-10-27 15 views
7

Estoy tratando de leer algunos XML recibidos de una interfaz externa sobre un socket. El problema es que la codificación se especifica incorrectamente en el encabezado XML (dice iso-8859-1, pero es utf-16BE). Está documentado que la codificación es utf-16BE, pero aparentemente olvidaron establecer la codificación correcta.Ignorando la codificación especificada al deserializar XML

para ignorar la codificación cuando Deserialize utilizo un StringReader así:

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

Lo anterior funciona realmente bien, pero no me gusta la parte en la que omita la línea de cabecera llamando ReadLine. ¿Hay alguna manera menos frágil de eludir la codificación especificada en el encabezado XML?

Solución con StreamReader

Mediante el uso de un StreamReader, I puede anular la codificación especificada en el XML-cabecera. Especificar XmlReaderSettings.IgnoreProcessingInstructions o no hizo ninguna diferencia. Curiosamente, StreamReader ignora la codificación especificada si encuentra una marca de orden de bytes Unicode.

Para recapitular:

  • Si el XmlReader se inicializa con un TextReader, codificación XML-cabecera es ignorado.
  • Si se utiliza un StringReader, el XmlReader falla si existe una marca de orden de bytes Unicode.
  • Si se utiliza un StreamReader, una marca de orden de bytes unicode anula la codificación de StreamReader.
  • XmlReaderSettings.IgnoreProcessingInstructions = true no hace la diferencia cuando se utiliza un TextReader.

En conclusión, la solución más robusta parece ser el uso de un StreamReader, ya que utiliza la marca de orden de bytes, si está presente.

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

Respuesta

2

Creo que sólo haría uso de un StreamReader, construido con la codificación correcta y paso a que el método XmlReader.Create (TextStream):

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

Si no hay otras instrucciones de procesamiento relevantes, que sólo puede ignorarlos estableciendo XmlReaderSettings.IgnoreProcessingInstructions.

+1

Gran! ¿Cómo especificaría la codificación "verdadera" entonces? (un XmlReader basado en un StringReader arroja una excepción incluso con IgnoreProcessingInstructions establecido en verdadero). – Holstebroe

Cuestiones relacionadas