Trevor Elliott
Trevor Elliott

Reputation: 11252

Serialize compact XML

I have a class with four fields (DateTime, Enum, string, string). I want to serialize it to and from an XML element or a series of XML elements in a compact manner. For example, I might serialize it to something like this:

<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>

Where 'i' is each class instance, 't' is the DateTime ticks, 'a' is the enum value, and the elements are strings.

I'd prefer to not have a root element, but if I do have it, I'd like it to be as small as possible.

I've tried using XmlSerializer with the XmlWriterSettings class but I can't get rid of the namespaces and root element.

What's the best way of doing this? I'm not saving to a file, I'm reading and writing to strings in memory.

Upvotes: 1

Views: 1034

Answers (4)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727077

If your data is that simple, you can use XmlWriter directly:

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());
}

Running this program produces the following output (I added line breaks for clarity; they are not in the output):

<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>

You need that root element if you would like to read the information back. The most expedient way would be using 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();

Upvotes: 1

L.B
L.B

Reputation: 116188

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();

and to read

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:

You don't need to convert xElem to string in order to use that xml in memory

Upvotes: 2

Zenexer
Zenexer

Reputation: 19621

You'll need to implement your own serializer, I believe, which will be a pain. That, or you could manually strip out what you don't need after serializing, which could work.

If size is your concern, you should be serializing to binary using BinaryFormatter. You can always base-64 encode it if you need to store it as a string. (BinaryFormatter works almost just like XmlSerializer, except the output is raw binary, rather than nicely formatted XML.)

Upvotes: 0

Matt Grande
Matt Grande

Reputation: 12157

I'd just use a StringBuilder, personally.

If size is your #1 concern, consider json or yaml instead of XML.

Upvotes: 0

Related Questions