XMLReader перерывается на BOM UTF-8
-
29-09-2019 - |
Вопрос
У меня есть следующий анализ XML в моем приложении:
public static XElement Parse(string xml, string xsdFilename)
{
var readerSettings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
Schemas = new XmlSchemaSet()
};
readerSettings.Schemas.Add(null, xsdFilename);
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
readerSettings.ValidationEventHandler +=
(o, e) => { throw new Exception("The provided XML does not validate against the request's schema."); };
var readerContext = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.UTF8);
return XElement.Load(XmlReader.Create(new StringReader(xml), readerSettings, readerContext));
}
Я использую его для разбора строк, отправляемых в мою службу WCF в документы XML, для пользовательской дезерриализации.
Он работает нормально, когда я читаю в файлах и отправляю их через провод (запрос); Я проверил, что спецификация не отправляется напротив. В моем запросе обработчик я сериализацию объекта ответа и отправляя его обратно в виде строки. Процесс сериализации добавляет BOM UTF-8 на переднюю часть строки, что приводит к тому же коду, чтобы сломаться при расстановке ответа.
System.Xml.XmlException : Data at the root level is invalid. Line 1, position 1.
В исследовании я проделал в течение последнего часа или около того, кажется, что XmlReader должен почтить отс. Если я вручную снимаю спереди спереди строки, ответа XML разбирается нормально.
Я упускаю что-то очевидное или хотя бы что-то коварное?
РЕДАКТИРОВАТЬ: Вот код сериализации, который я использую для возврата ответа:
private static string SerializeResponse(Response response)
{
var output = new MemoryStream();
var writer = XmlWriter.Create(output);
new XmlSerializer(typeof(Response)).Serialize(writer, response);
var bytes = output.ToArray();
var responseXml = Encoding.UTF8.GetString(bytes);
return responseXml;
}
Если это просто вопрос XML, неверно, содержащий спектр, то я переключусь на
var responseXml = new UTF8Encoding(false).GetString(bytes);
Но вообще не было ясно от моих исследований, что СБ был незаконным в реальном этапе XML; увидеть, например, C # Обнаружение XML кодирования из байтового массива?
Решение
Строка XML не должна (!) Содержать BOM, BOM разрешен только в байтовых данных (например, потоках), которые кодируются с UTF-8. Это связано с тем, что строковое представление не кодируется, но уже последовательность символов Unicode.
Поэтому кажется, что вы загружаете неправильную строку, которая находится в коде, которую вы, к сожалению, не предоставили.
Редактировать:
Спасибо за размещение кода сериализации.
Вы не должны писать данные в MemoryStream, а скорее в StringWriter, который вы можете преобразовать в строку с TOSTRING. Поскольку это избегает прохождения через представление байта, это не только быстрее, но и позволяет избежать таких проблем.
Что-то вроде этого:
private static string SerializeResponse(Response response)
{
var output = new StringWriter();
var writer = XmlWriter.Create(output);
new XmlSerializer(typeof(Response)).Serialize(writer, response);
return output.ToString();
}
Другие советы
В моем запросе обработчик я сериализацию объекта ответа и отправляя его обратно в виде строки. Процесс сериализации добавляет BOM UTF-8 на переднюю часть строки, что приводит к тому же коду, чтобы сломаться при расстановке ответа.
Таким образом, вы хотите предотвратить добавление СБ в рамках процесса вашего сериализации. К сожалению, вы не предоставляете, какова ваша логика сериализации.
Что вы должны сделать, это обеспечить Utf8encoding. экземпляр создан через UTF8ENCODING (BOOL) Конструктор для отключения генерации СБ, и пропустите это Encoding
Экземпляр к тому, что методы, которые вы используете, которые генерируют вашу промежуточную строку.
Стук не должен быть в строке в первую очередь.
Boms используются для обнаружения кодирования необработанного байтового массива; У них нет бизнеса в реальной строке.
От чего приходит строка?
Вы, вероятно, читаете это с неправильным кодированием.
Строки в C # кодируются как UTF-16, поэтому BOM будет неправ. Как правило, всегда кодируйте XML для байтовых массивов и декодируйте его из байтовых массивов.