Сериализация компактного XML - PullRequest
1 голос
/ 10 февраля 2012

У меня есть класс с четырьмя полями (DateTime, Enum, string, string). Я хочу компактно преобразовать его в серию и из элемента XML или серии элементов XML. Например, я мог бы сериализовать это что-то вроде этого:

<i t='234233' a='3'><u>Username1</u><s1>This is a string</s1></i>
<i t='234233' a='4'><u>Username2</u><s1>This is a string</s1></i>
<i t='223411' a='1'><u>Username3</u><s1>This is a string</s1></i>

Где 'i' - каждый экземпляр класса, 't' - тики DateTime, 'a' - значение перечисления, а элементы - строки.

Я бы предпочел не иметь корневого элемента, но если он у меня есть, я бы хотел, чтобы он был как можно меньшим.

Я пытался использовать XmlSerializer с классом XmlWriterSettings, но не могу избавиться от пространств имен и корневого элемента.

Какой лучший способ сделать это? Я не сохраняю в файл, я читаю и записываю строки в память.

Ответы [ 4 ]

2 голосов
/ 10 февраля 2012

System.Xml.Linq

XElement xElem = new XElement("r");
for (int i = 0; i < 3; i++)
{
    xElem.Add(
        new XElement("i",
                new XAttribute("t", "234233"),
                new XAttribute("a", "3"),
                new XElement("u", "UserName"),
                new XElement("s1", "This is a string")
        )
    );
}
var str = xElem.ToString();

и читать

XElement xElem2 = XElement.Load(new StringReader(str));
foreach(var item in xElem2.Descendants("i"))
{
    Console.WriteLine(item.Attribute("t").Value + " " + item.Element("u").Value);
}

PS:

Вам не нужно преобразовывать xElem в строку, чтобы использовать этот xml в памяти

1 голос
/ 10 февраля 2012

Если ваши данные настолько просты, вы можете использовать XmlWriter напрямую:

class Data {
    public DateTime Date { get; set; }
    public int Code { get; set; }
    public string First { get; set; }
    public string Last { get; set; }
}

static void Main() {
    var sb = new StringBuilder();
    var xws = new XmlWriterSettings();
    xws.OmitXmlDeclaration = true;
    xws.Indent = false;
    var elements = new[] {
        new Data { Date = DateTime.Now, First = "Hello", Last = "World", Code = 2}
    ,   new Data { Date = DateTime.UtcNow, First = "Quick", Last = "Brown", Code = 4}
    };
    using (var xw = XmlWriter.Create(sb, xws)) {
        xw.WriteStartElement("root");
        foreach (var d in elements) {
            xw.WriteStartElement("i");
            xw.WriteAttributeString("t", ""+d.Date);
            xw.WriteAttributeString("a", "" + d.Code);
            xw.WriteElementString("u", d.First);
            xw.WriteElementString("s1", d.Last);
            xw.WriteEndElement();
        }
        xw.WriteEndElement();
    }
    Console.WriteLine(sb.ToString());
}

Запуск этой программы приводит к следующему выводу (для ясности я добавил разрывы строк; в выводе они не ):

<root>
<i t="2/9/2012 3:16:56 PM" a="2"><u>Hello</u><s1>World</s1></i>
<i t="2/9/2012 8:16:56 PM" a="4"><u>Quick</u><s1>Brown</s1></i>
</root>

Вам нужен этот корневой элемент, если вы хотите прочитать информацию обратно. Наиболее целесообразно использовать LINQ2XML :

var xdoc = XDocument.Load(new StringReader(xml));
var back = xdoc.Element("root").Elements("i").Select(
    e => new Data {
        Date = DateTime.Parse(e.Attribute("t").Value)
    ,   Code = int.Parse(e.Attribute("a").Value)
    ,   First = e.Element("u").Value
    ,   Last = e.Element("s1").Value
    }
).ToList();
0 голосов
/ 10 февраля 2012

Я полагаю, вам нужно будет реализовать свой собственный сериализатор, что будет проблемой. Это, или вы могли бы вручную вырезать то, что вам не нужно после сериализации, что может сработать.

Если вас интересует размер, вы должны сериализовать в двоичный файл, используя BinaryFormatter. Вы всегда можете закодировать его в base-64, если вам нужно сохранить его в виде строки. (BinaryFormatter работает почти так же, как XmlSerializer, за исключением того, что на выходе получается простой двоичный файл, а не красиво отформатированный XML.)

0 голосов
/ 10 февраля 2012

Я бы просто использовал StringBuilder, лично.

Если размер является вашей проблемой # 1, рассмотрите json или yaml вместо XML.

...