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

时间:2013-08-08 17:26:41

标签: c# xml serialization xml-serialization

我需要使用嵌套属性创建一些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; }
}

6 个答案:

答案 0 :(得分:3)

尝试使用XDocument。与XML Serializer相比,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");

答案 1 :(得分:1)

XmlElement属性会让你达到一个深度,如下所示:

[XmlElement(ElementName = "1"]
public string 1 { get; set; }

但这不符合您的需求,所以......

查看YAXLib: Yet Another XML Serialization Library for the .NET Framework

声称拥有support for specifying path-like serialization addresses, e.g., elem1/elem2/elem3, and ../elem1, and ./elem1

答案 2 :(得分:1)

仅仅因为我喜欢用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>

答案 3 :(得分:0)

据我所知,您的选择仅限于此:

1)让您的类结构反映XML结构并使用简单的框架注释 - 这是您已经提到过的厌恶的嵌套类成员结构。

2)实现IXmlSerializable并执行自定义序列化。毕竟,这自定义序列化。

答案 4 :(得分:0)

你可以尝试一个带有自引用的类,比如下面的文字:

    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>

答案 5 :(得分:0)

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

还有其他一些选择。