Как правильно сериализовать строку, содержащую ничего, кроме "\ r \ n", в XML? - PullRequest
2 голосов
/ 23 августа 2009

Мы используем DataContractSerializer для сериализации наших данных в XML. Недавно мы обнаружили ошибку, связанную с тем, как строка "\r\n" сохраняется и читается обратно - она ​​превратилась в "\n". Очевидно, что это вызвано использованием XmlWriter с набором Indent = true:

// public class Test { public string Line; }

var serializer = new DataContractSerializer(typeof(Test));

using (var fs = File.Open("C:/test.xml", FileMode.Create))
using (var wr = XmlWriter.Create(fs, new XmlWriterSettings() { Indent = true }))
    serializer.WriteObject(wr, new Test() { Line = "\r\n" });

Test test;
using (var fs = File.Open("C:/test.xml", FileMode.Open))
    test = (Test) serializer.ReadObject(fs);

Очевидное решение состоит в том, чтобы прекратить делать отступ в XML, и действительно удаление строки "XmlWriter.Create" делает правильное возвращение значения Line, будь то "\n", "\r\n" или что-то еще.

Тем не менее, способ, которым DataContractSerializer пишет, все же кажется не совсем безопасным или, возможно, даже правильным - например, простое чтение полученного файла с помощью XML Notepad и его повторное сохранение разрушает как "\n", так и "\r\n" значения полностью.

Какой правильный подход здесь? Является ли использование XML в качестве формата для сериализации двоичных данных ошибочной концепцией? Неправильно ли ожидать, что такие инструменты, как XML Notepad, не повредят нашим данным? Нужно ли дополнять каждое string поле, которое может содержать такой текст, с помощью какого-либо специального атрибута, возможно, для принудительной установки CDATA?

Ответы [ 2 ]

3 голосов
/ 23 августа 2009

Потенциально вы могли бы использовать CDATA, но я согласен с вашим резюме, что использование XML для сериализации двоичных данных просто неправильно. Можете ли вы передать данные другим способом?

1 голос
/ 23 августа 2009

Почему важно различать строку, содержащую '\ r \ n', и пустую строку? В общем, при использовании сериализации контракта данных вас не волнует формат / структура XML или то, как он хранит данные при условии, что они совершают «круговую передачу» правильно.

Вот как мы это используем:

DataContractSerializer serializer = CreateSerializer(this.GetType());
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (XmlWriter writer = XmlTextWriter.Create(sb, settings))
{
   serializer.WriteObject(writer, this);
   writer.Flush();
}


internal static T Deserialize<T>(Stream stream)
{
   DataContractSerializer serializer = CreateSerializer(typeof(T));
   return (T)serializer.ReadObject(stream);
}

public static DataContractSerializer CreateSerializer(Type type)
{
   DataContractSerializer serializer = new DataContractSerializer();
   return serializer;
}

Если я не ошибаюсь, такие символы, как перевод строки, не являются допустимыми символами в пределах значения XML, и их необходимо кодировать или ограничивать в разделе CDATA. Сериализатор контракта данных не делает ни того, ни другого. Такие инструменты, как XML Notepad, изменяют данные, потому что они понимают, что это недопустимые символы, и удаляют их, чтобы создать соответствующий XML.

На самом деле неудивительно, что строковые данные могут возвращаться по-разному между двоичным сериализатором и XML-сериализатором. Бинарный сериализатор будет сериализовать точное двоичное представление бита данных для бита и не будет иметь «правил» в отношении того, что является допустимым символом и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...