У меня есть следующий 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 не отправляется через. В моем обработчике запросов я сериализирую объект ответа и передаю его обратно как строку. Процесс сериализации добавляет BOM UTF-8 к передней стороне строки, которая заставляет тот же код повреждаться при парсинге ответа.
System.Xml.XmlException : Data at the root level is invalid. Line 1, position 1.
В исследовании я сделал за прошлый час или так, кажется, что XmlReader должен соблюдать BOM. Если я вручную удаляю BOM из передней стороны строки, ответ 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, неправильно содержащего BOM, то я переключусь на
var responseXml = new UTF8Encoding(false).GetString(bytes);
но не было ясно вообще из моего исследования, что BOM был недопустим в фактической строке XML; посмотрите, например, c# Обнаруживают xml, кодирующий от Массива байтов?
Строка xml не должна (!) Содержать спецификацию, спецификация допускается только в байтовых данных (например, потоках), которые закодированы с помощью UTF-8. Это связано с тем, что строковое представление не закодировано, а уже представляет собой последовательность символов Юникода.
Таким образом, кажется, что вы загрузили неверную строку, которая находится в коде, который вы, к сожалению, не предоставили.
Редактировать:
Спасибо за размещение кода сериализации.
Вы должны записывать данные не в 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();
}
В моем обработчике запросов я сериализую объект ответа и отправляю его обратно в виде строки. Процесс сериализации добавляет спецификацию UTF-8 в начало строки, что приводит к сбою того же кода при синтаксическом анализе ответа.
Итак, вы хотите предотвратить добавление спецификации как часть процесса сериализации. К сожалению, вы не предоставляете свою логику сериализации.
Что вам нужно сделать, так это предоставить экземпляр UTF8Encoding , созданный с помощью конструктора UTF8Encoding (bool) , чтобы отключить создание спецификации, и передать этот экземпляр Encoding
. к каким бы методам вы не использовали, которые генерируют вашу промежуточную строку.
Спецификация не должна быть в строке.
Спецификации используются для обнаружения кодировки необработанного байтового массива; им нечего делать в реальной строке.
Откуда берется струна?
Вероятно, вы читаете его с неправильной кодировкой.
Строки в C# кодируются как UTF-16, поэтому BOM будет неверным. Как правило, всегда кодируйте XML в байтовые массивы и декодируйте его из байтовых массивов.