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);
}
}
}
}
Great! Jak zatem określić "prawdziwe" kodowanie? (XmlReader oparty na StringReaderze zgłasza wyjątek nawet przy ustawieniu wartości true dla IgnoreProcessingInstructions). – Holstebroe