【问题标题】:Can I serialize a single object into nested XML?我可以将单个对象序列化为嵌套 XML 吗?
【发布时间】:2013-08-08 17:26:41
【问题描述】:

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

【问题讨论】:

  • 你可以使用 IXmlSerializable 并实现 WriteXml 方法吗? msdn.microsoft.com/en-us/library/…
  • 您是否有机会使用 XDocument 代替?使用 XDocument 比使用 XML 序列化程序要容易得多,而且您可以轻松嵌套 XElement。
  • @leon 我可以,我只是希望避免它。需要生成的 XML 相当复杂,需要一些工作
  • @ZachSmith 当然,我的做法没有限制,我只是在寻找最好的方法。谢谢 我去看看
  • 请将您的解决方案发布为答案,而不是更新您的问题。这是为了帮助未来的访客并避免混淆。谢谢。

标签: c# xml serialization xml-serialization


【解决方案1】:

尝试改用 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");

【讨论】:

  • 这看起来很有希望,我会进一步研究这个选项。谢谢
  • 这是构建 XML 文档的最佳选择。
【解决方案2】:

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

    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

    【讨论】:

    • 是的,不幸的是,一层深度还不够,但是 YAXLib 看起来很有前途,谢谢
    • 是的,YAXLib 正是我想要的!虽然我很想自己写一些东西,因为它是一个开源项目,我能够将代码集成到我们的框架中以获得相同的结果。谢谢
    【解决方案4】:

    据我所知,您的选择有限:

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

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

    【讨论】:

      【解决方案5】:

      您可以尝试使用自引用的类,如下所示:

          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>
      

      【讨论】:

      • 有趣的方法,但会涉及编写我试图避免的复杂类。不过谢谢
      【解决方案6】:

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

      还有很多其他选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-28
        • 2011-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多