序列化紧凑的XML

时间:2012-02-09 20:01:23

标签: c# xml xml-serialization

我有一个包含四个字段的类(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 个答案:

答案 0 :(得分:2)

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 :(得分:1)

如果您的数据很简单,可以直接使用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();

答案 2 :(得分:0)

我个人使用StringBuilder

如果尺寸是您的第一关注点,请考虑使用jsonyaml而不是XML。

答案 3 :(得分:0)

我相信你需要实现自己的序列化程序,这将是一个痛苦。那,或者你可以手动去除序列化后你不需要的东西,这可能有效。

如果您关注大小,则应使用BinaryFormatter序列化为二进制。如果需要将其存储为字符串,则可以始终对其进行base-64编码。 (BinaryFormatter几乎就像XmlSerializer一样,除了输出是原始二进制文件,而不是格式良好的XML。)