C# 将类列表序列化为 XML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/178899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:47:48  来源:igfitidea点击:

Serializing Lists of Classes to XML

c#xmlserialization

提问by Jon Artus

I have a collection of classes that I want to serialize out to an XML file. It looks something like this:

我有一组要序列化为 XML 文件的类。它看起来像这样:

public class Foo
{
  public List<Bar> BarList { get; set; }
}

Where a bar is just a wrapper for a collection of properties, like this:

其中 bar 只是一组属性的包装器,如下所示:

public class Bar
{
  public string Property1 { get; set; }
  public string Property2 { get; set; }
}

I want to mark this up so that it outputs to an XML file - this will be used for both persistence, and also to render the settings via an XSLT to a nice human-readable form.

我想标记它以便它输出到一个 XML 文件 - 这将用于持久性,并通过 XSLT 将设置呈现为一个很好的人类可读的形式。

I want to get a nice XML representation like this:

我想得到这样一个很好的 XML 表示:

<?xml version="1.0" encoding="utf-8"?>
<Foo>
  <BarList>
    <Bar>
      <Property1>Value</Property1>
      <Property2>Value</Property2>   
    </Bar>
    <Bar>
      <Property1>Value</Property1>
      <Property2>Value</Property2>   
    </Bar>
  </Barlist>
</Foo>

where are all of the Bars in the Barlist are written out with all of their properties. I'm fairly sure that I'll need some markup on the class definition to make it work, but I can't seem to find the right combination.

Barlist 中的所有 Bars 在哪里都写出了它们的所有属性。我相当确定我需要在类定义上进行一些标记才能使其工作,但我似乎无法找到正确的组合。

I've marked Foo with the attribute

我用属性标记了 Foo

[XmlRoot("Foo")]  

and the list<Bar>with the attribute

list<Bar>属性

[XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName="Bar")]

in an attempt to tell the Serializer what I want to happen. This doesn't seem to work however and I just get an empty tag, looking like this:

试图告诉序列化程序我想要发生什么。然而,这似乎不起作用,我只是得到一个空标签,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Foo> 
  <Barlist />
</Foo>

I'm not sure if the fact I'm using Automatic Properties should have any effect, or if the use of generics requires any special treatment. I've gotten this to work with simpler types like a list of strings, but a list of classes so far eludes me.

我不确定我使用自动属性的事实是否应该有任何影响,或者泛型的使用是否需要任何特殊处理。我已经使用它来处理更简单的类型,比如字符串列表,但到目前为止我还没有使用类列表。

采纳答案by Carl

Just to check, have you marked Bar as [Serializable]?

只是为了检查一下,您是否将 Bar 标记为 [Serializable]?

Also, you need a parameter-less ctor on Bar, to deserialize

此外,您需要在 Bar 上使用无参数构造函数来反序列化

Hmm, I used:

嗯,我用过:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {

        Foo f = new Foo();

        f.BarList = new List<Bar>();

        f.BarList.Add(new Bar { Property1 = "abc", Property2 = "def" });

        XmlSerializer ser = new XmlSerializer(typeof(Foo));

        using (FileStream fs = new FileStream(@"c:\sertest.xml", FileMode.Create))
        {
            ser.Serialize(fs, f);
        }
    }
}

public class Foo
{
    [XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName = "Bar")]
    public List<Bar> BarList { get; set; }
}

[XmlRoot("Foo")]
public class Bar
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

And that produced:

这产生了:

<?xml version="1.0"?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <BarList>
    <Bar>
      <Property1>abc</Property1>
      <Property2>def</Property2>
    </Bar>
  </BarList>
</Foo>

回答by FryHard

Everything looks great. As @Carl said you need to add the [Serializable]attibute to your classes, but other than that your XML creation should work find.

一切看起来都很棒。正如@Carl 所说,您需要将[Serializable]属性添加到您的类中,但除此之外,您的 XML 创建应该可以找到。

Foo

[Serializable]
[XmlRoot("Foo")]
public class Foo
{
    [XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName = "Bar")]
    public List<Bar> BarList { get; set; }
}

Bar

酒吧

[Serializable]
public class Bar
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

Code to test

要测试的代码

Foo f = new Foo();
f.BarList = new List<Bar>();
f.BarList.Add(new Bar() { Property1 = "s", Property2 = "2" });
f.BarList.Add(new Bar() { Property1 = "s", Property2 = "2" });

FileStream fs = new FileStream("c:\test.xml", FileMode.OpenOrCreate);
System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(Foo));
s.Serialize(fs, f);

Output

输出

<?xml version="1.0" ?> 
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <BarList>
        <Bar>
            <Property1>s</Property1> 
            <Property2>2</Property2> 
        </Bar>
        <Bar>
            <Property1>s</Property1> 
            <Property2>2</Property2> 
        </Bar>
    </BarList>
</Foo>

回答by Peter Klein

It has been over 5 years since this item was posted. I give my experience from July 2013 (.NET Framework 4.5). For what it's worth and to whom it may concern:

这篇文章发布已经超过 5 年了。我提供了 2013 年 7 月的经验(.NET Framework 4.5)。对于它的价值以及它可能涉及的对象:

When I define a class like so: (VB.Net code)

当我像这样定义一个类时:(VB.Net 代码)

<Serializable> Public Class MyClass
    Public Property Children as List(of ChildCLass)
    <XmlAttribute> Public Property MyFirstProperty as string
    <XmlAttribute> Public Property MySecondProperty as string
End Class

<Serializable> Public Class ChildClass
    <XmlAttribute> Public Property MyFirstProperty as string
    <XmlAttribute> Public Property MySecondProperty as string
End Class

With this definition the class is (de)serialized without any problems. This is the XML that comes out of here:

有了这个定义,这个类就被(反)序列化了,没有任何问题。这是从这里出来的 XML:

<MyClass> MyFirstProperty="" MySecondProperty=""
    <Children>
        <ChildClass> MyFirstProperty="" MySecondProperty=""
        </ChildClass>
   </Children>
</MyClass>

It only took me two days to figure it out that the solution was to leave out the <XmlElement>prefix of the List(of T) elements.

我只花了两天时间就弄清楚解决方案是省略<XmlElement>List(of T) 元素的前缀。

回答by Lê Quy ??n

var xmlfromLINQ = new XElement("BarList",
            from c in BarList 
            select new XElement("Bar",
                new XElement("Property1", c.Property1),
                new XElement("Property2", c.Property2)
             ));