我可以将单个对象序列化为嵌套的XML吗
本文关键字:嵌套 XML 序列化 单个 对象 我可以 | 更新日期: 2023-09-27 18:26:59
我需要创建一些具有嵌套属性的XML,这些属性看起来类似于以下内容:
<1>
<1a>
Some stuff
</1a>
<1b>
Some stuff
<1c>
Some stuff
</1c>
</1b>
</1>
通常,为了创建嵌套元素,对象内部有嵌套类。然而,我需要创建的XML会导致对象内部有20多个嵌套类,这对我来说很可怕。没有一个元素是重复的,所以我认为没有必要创建所有这些类。
有没有一种方法可以告诉XML序列化程序嵌套元素?例如,类中的一个属性:
public class XMLExport
{
[DataMember(Order = 0, Name = "1")]
public string 1 { get; set; }
[DataMember(Order = 1, Name = "1/1a")]
public string 1a { get; set; }
[DataMember(Order = 2, Name = "1/1b")]
public string 1b { get; set; }
[DataMember(Order = 3, Name = "1/1b/1c")]
public string 1c { get; set; }
}
尝试使用XDocument。与XML序列化程序相比,XDocuments非常好用,而且很容易使用。它的MSDN文档非常棒。http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx
使用他们的示例,您可以创建这样的示例xml文件:
XDocument srcTree = new XDocument(
new XComment("This is a comment"),
new XElement("1",
new XElement("1a", "Some Stuff"),
new XElement("1b",
new XElement("1c", "Some Stuff"
)
)
);
然后只保存
srcTree.save("path'to'file");
因为我喜欢用LINQ做事情,这里有一个替代方案:
假设你有一个这样的类:
public class lClass
{
public string la{get;set;}
public string lb{get;set;}
public string lc{get;set;}
}
你有一个这类的列表:
List<lClass> l = new List<lClass>();
l.Add(new lClass{la ="1 Some Stuff a",lb ="1 Some Stuff b",lc = "1 Some Stuff c"});
l.Add(new lClass{la ="2 Some Stuff a",lb ="2 Some Stuff b",lc = "2 Some Stuff c"});
l.Add(new lClass{la ="3 Some Stuff a",lb ="3 Some Stuff b",lc = "3 Some Stuff c"});
l.Add(new lClass{la ="4 Some Stuff a",lb ="4 Some Stuff b",lc = "4 Some Stuff c"});
带有以下代码:
XElement xe = new XElement("root");
xe.Add
(
l.Select
(
x =>
new XElement
(
"l",
new XElement
(
"la",
x.la
),
new XElement
(
"lb",
x.lb,
new XElement
(
"lc",
x.lc
)
)
)
)
);
你得到:
<root>
<l>
<la>1 Some Stuff a</la>
<lb>1 Some Stuff b<lc>1 Some Stuff c</lc></lb>
</l>
<l>
<la>2 Some Stuff a</la>
<lb>2 Some Stuff b<lc>2 Some Stuff c</lc></lb>
</l>
<l>
<la>3 Some Stuff a</la>
<lb>3 Some Stuff b<lc>3 Some Stuff c</lc></lb>
</l>
<l>
<la>4 Some Stuff a</la>
<lb>4 Some Stuff b<lc>4 Some Stuff c</lc></lb>
</l>
</root>
XmlElement
属性将使您达到一个级别的深度,如下所示:
[XmlElement(ElementName = "1"]
public string 1 { get; set; }
但这不能满足你的需求,所以…
看看YAXLib:另一个.NET框架的XML序列化库。
它声称有support for specifying path-like serialization addresses, e.g., elem1/elem2/elem3, and ../elem1, and ./elem1
。
据我所知,您的选择在这里是有限的:
1) 让您的类结构反映XML结构,并使用简单的框架注释——这是您已经提到的不喜欢的嵌套类成员结构。
2) 实现IXmlSerializable并执行自定义序列化。毕竟,这个是自定义序列化。
您可以尝试一个具有自引用的类,如下所示:
public class Item
{
public string Value { get; set; }
public Item[] ChildList { get; set; }
}
然后你会有以下内容:
var obj = new Item
{
Value = "Something",
ChildList = new[]
{
new Item
{
Value = "Something",
ChildList = new[]
{
new Item
{
Value = "Something",
ChildList = new[] { new Item() {Value = "End"} }
}
}
}
}
};
var serializer = new XmlSerializer(typeof(Item));
using (var writer = new StringWriter())
{
serializer.Serialize(writer, obj);
Console.WriteLine(writer.ToString());
Console.Read();
}
输出:
<?xml version="1.0" encoding="utf-16"?>
<Item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Value>Something</Value>
<ChildList>
<Item>
<Value>Something</Value>
<ChildList>
<Item>
<Value>Something</Value>
<ChildList>
<Item>
<Value>End</Value>
</Item>
</ChildList>
</Item>
</ChildList>
</Item>
</ChildList>
</Item>
感谢Karls的回答,我使用了YAXLib来完成这项工作,它提供了如下漂亮整洁的类:
public class XMLExport
{
[YAXElementFor("")]
[YAXSerializeAs("1")]
public string 1 { get; set; }
[YAXElementFor("1")]
[YAXSerializeAs("1a")]
public string 1a { get; set; }
[YAXElementFor("1")]
[YAXSerializeAs("1b")]
public string 1b { get; set; }
[YAXElementFor("1/1a/1b")]
[YAXSerializeAs("1c")]
public string 1c { get; set; }
}
YAXElementFor
允许您放置一个路径,以便嵌套元素。
YAXSerializeAs
允许您更改元素的名称,以防它需要与属性名称不同。
还有很多其他选择。