2010-10-27 18 views
7

Sto provando a leggere alcuni XML ricevuti da un'interfaccia esterna tramite un socket. Il problema è che la codifica è specificata erroneamente nell'intestazione XML (si dice iso-8859-1, ma è utf-16BE). È documentato che la codifica è utf-16BE, ma a quanto pare hanno dimenticato di impostare la codifica corretta.Ignorare la codifica specificata durante la deserializzazione XML

Per ignorare la codifica quando deserializzare utilizzo uno StringReader simili:

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

che questo effettivamente funziona bene, ma non piace la parte in cui saltare la linea di intestazione chiamando ReadLine. C'è un modo meno fragile per bypassare la codifica specificata nell'intestazione XML?

Soluzione con StreamReader

Utilizzando uno StreamReader, posso ignorare la codifica specificata nel XML-header. La specifica di XmlReaderSettings.IgnoreProcessingInstructions o non ha fatto alcuna differenza. È interessante notare che StreamReader ignora la codifica specificata se trova un contrassegno di ordine byte unicode.

Per ricapitolare:

  • Se il XmlReader viene inizializzato con un TextReader, codifica XML-header viene ignorato.
  • Se viene utilizzato un oggetto StringReader, XmlReader ha esito negativo se esiste un segno di ordine byte unicode.
  • Se viene utilizzato uno StreamReader, un segno di ordine byte unicode sostituisce la codifica StreamReader.
  • XmlReaderSettings.IgnoreProcessingInstructions = true non fa la differenza quando si utilizza TextReader.

In conclusione, la soluzione più solida sembra utilizzare un StreamReader, poiché utilizza il segno di ordine dei byte, se 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); 
       } 
      } 
     } 
    } 

risposta

2

penso mi basta usare uno StreamReader, costruito con la codifica a destra e passo che al metodo XmlReader.Create (TextStream):

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

Se non ci sono altre istruzioni di elaborazione rilevanti, si può semplicemente ignorare impostando XmlReaderSettings.IgnoreProcessingInstructions.

+1

Grande! Come dovrei specificare la codifica "vera" allora? (un XmlReader basato su StringReader genera un'eccezione anche se IgnoreProcessingInstructions è impostato su true). – Holstebroe

Problemi correlati