2010-10-27 11 views
7

Próbuję odczytać niektóre XML odebrane z interfejsu zewnętrznego przez gniazdo. Problem polega na tym, że kodowanie jest błędne w nagłówku XML (mówi iso-8859-1, ale jest to utf-16BE). Udokumentowano, że kodowanie jest utf-16BE, ale najwyraźniej zapomnieli ustawić poprawne kodowanie.Ignorowanie określonego kodowania podczas deserializacji XML

Aby zignorować kodowanie kiedy deserializowania używam StringReader tak:

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

Powyższy faktycznie działa dobrze, ale nie podoba mi się część, w której po prostu pominąć wiersz nagłówka nazywając ReadLine. Czy istnieje mniej kruchy sposób na ominięcie kodowania określonego w nagłówku XML?

Rozwiązanie z StreamReader

Przy użyciu StreamReader, mogę zmienić kodowanie określone w XML-cel. Określanie XmlReaderSettings.IgnoreProcessingInstructions lub nie robiło żadnej różnicy. Co ciekawe, StreamReader ignoruje określone kodowanie, jeśli znajdzie znak porządku bajtowego w kodzie Unicode.

Reasumując:

  • Jeśli XmlReader jest inicjowany z TextReader, kodowanie XML-header jest ignorowany.
  • Jeśli używany jest StringReader, XmlReader kończy się niepowodzeniem, jeśli istnieje znak kolejności bajtów w kodzie Unicode.
  • Jeśli używany jest StreamReader, znacznik kolejności bajtów unicode zastępuje kodowanie StreamReader.
  • XmlReaderSettings.IgnoreProcessingInstructions = true nie robi różnicy podczas korzystania z TextReader.

Podsumowując, najbardziej wydajnym rozwiązaniem wydaje się być użycie StreamReadera, ponieważ używa znaku kolejności bajtów, jeśli jest obecny.

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

Odpowiedz

2

myślę, że wystarczy użyć StreamReader, zbudowany z prawej kodowania i przekazać, że metody XmlReader.Create (TextStream):

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

Jeśli nie istnieją żadne inne odpowiednie instrukcje przetwarzania, można po prostu zignorować je przez ustawienie XmlReaderSettings.IgnoreProcessingInstructions.

+1

Great! Jak zatem określić "prawdziwe" kodowanie? (XmlReader oparty na StringReaderze zgłasza wyjątek nawet przy ustawieniu wartości true dla IgnoreProcessingInstructions). – Holstebroe

Powiązane problemy