我可以将单个对象序列化为嵌套的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; }
}

我可以将单个对象序列化为嵌套的XML吗

尝试使用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允许您更改元素的名称,以防它需要与属性名称不同。

还有很多其他选择。

相关文章: