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