C# Linq XML to对象,其中XML节点具有嵌套元素

C# Linq XML to对象,其中XML节点具有嵌套元素,c#,xml,winforms,linq,C#,Xml,Winforms,Linq,我需要从XML文档生成一个列表,而事件有一个列表。阅读时如何将XML转换为列表对象: 这是我的活动课: public class Event { public string id { get; set; } public string title { get; set; } public DateTime Start { get; set; } public DateTime End { get; set; } public virtual List<

我需要从XML文档生成一个
列表
,而
事件
有一个
列表
。阅读时如何将XML转换为
列表
对象:

这是我的活动课:

public class Event
{
    public string id { get; set; }
    public string title { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public virtual List<Contact> contacts { get; set; }
}
这就是当用户添加内容时保存XML文档的方式

<Event>
    <id>1</id>
    <title>AA</title>
    <start>2019-12-01T14:13:58.863</start>
    <end>2019-12-01T15:13:58.787</end>
    <contacts>

      <contact>
        <id>1</id>
        <name>ABC</name>
      </contact>

      <contact>
        <id>2</id>
        <name>ABCD</name>
      </contact>

      <contact>
        <id>3</id>
        <name>ABCDE</name>
      </contact>

    </contacts>
  </Event>

我对如何将项目读入列表感到惊讶。如何操作?

使用
System.Xml.Serialization
事件
对象保存/加载到Xml或从Xml加载。将创建的XML格式与您的非常相似

保存/加载
列表
的方法相同(在下面的exmapls中,
事件
需要替换为
列表

注意:下例中的加载(使用
XmlSerializer.Deserialize
)无法正确处理您创建的XML文件,它仅适用于保存示例创建的XML文件(使用
XmlSerializer.Serialize
)。要使用
XmlSerializer。使用您自己的XML文件反序列化
,需要向类属性添加
XmlElement
属性,并向
XmlSerializer
提供
XmlRootAttribute
(如中所示)。如果您可以使用
XmlSerializer.Serialize
创建XML文件,而不使用您已经创建的文件,那么您将节省额外的工作

事件
对象保存为XML(序列化)的示例:

从XML加载
事件
对象的示例(淡化):

将为
事件
对象创建的XML与文件中的内容相似(或相同):

<?xml version="1.0"?>
<Event xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <id>1</id>
  <title>AA</title>
  <Start>2019-12-01T14:13:58.863</Start>
  <End>2019-12-01T15:13:58.787</End>
  <contacts>
    <Contact>
      <Id>1</Id>
      <Name>ABC</Name>
    </Contact>
    <Contact>
      <Id>2</Id>
      <Name>ABCD</Name>
    </Contact>
    <Contact>
      <Id>3</Id>
      <Name>ABCDE</Name>
    </Contact>
  </contacts>
</Event>

1.
AA
2019-12-01T14:13:58.863
2019-12-01T15:13:58.787
1.
基础知识
2.
ABCD
3.
ABCDE

假设xml的根被称为事件:

<?xml version="1.0" encoding="UTF-8"?>
<Events>
    <Event>
        <id>1</id>
        <title>AA</title>
        <start>2019-12-01T14:13:58.863</start>
        <end>2019-12-01T15:13:58.787</end>
        <contacts>
            <contact>
                <id>1</id>
                <name>ABC</name>
            </contact>
            <contact>
                <id>2</id>
                <name>ABCD</name>
            </contact>
            <contact>
                <id>3</id>
                <name>ABCDE</name>
            </contact>
        </contacts>
    </Event>
    <Event>
        <id>2</id>
        <title>AA</title>
        <start>2019-12-02T14:13:58.863</start>
        <end>2019-12-02T15:13:58.787</end>
        <contacts>
            <contact>
                <id>4</id>
                <name>DEF</name>
            </contact>
            <contact>
                <id>5</id>
                <name>BNH</name>
            </contact>
            <contact>
                <id>6</id>
                <name>KLK</name>
            </contact>
        </contacts>
    </Event>
</Events>

为了掌握XmlSerializer,我建议您从这里开始并继续。

您可以对xml进行反序列化:您好,这很有效,谢谢您提供的链接,我将查看这些链接,我是c#新手,一切似乎都很奇怪。我可以用同样的方法从xml文件中获取特定节点并更新和保存吗it@mikeoconner不客气。我很高兴我帮了忙。@mikeoconner如果我必须得到一个特定的节点,更新并保存它,我会选择LINQ to XML。你可以从阅读有关它的文章开始。然后看看这样的答案,或者看看教程,它们很多。如果你需要任何特别的帮助。请提出另一个问题,具体说明问题所在。ThanksI尝试了这个方法,第一次它给了我一个错误,说RootTag不是预期的。然后,我在stackoverflow上找到了一个答案,即初始化序列化程序,比如XmlSerializer=newXmlSerializer(typeof(List),xRoot);一旦我这样做了,代码就被执行了,但是列表是空的
xmlSerializer.Deserialize的默认操作将不能正确地处理文件。我在回答中的意思是建议您使用
XmlSerializer.Serialize
创建XML文件首先,这样您的对象将以默认方式序列化为XML,
XmlSerializer.Deserialize
将正常工作。如果要使用已创建的文件,必须使用中的
xmlement
属性,并且需要在回答中提供
XmlRootAttribute
属性。如果您首先使用
XmlSerializer.Serialize
创建文件,那么您的工作量就会减少,不需要
xmlement
属性和
XmlRootAttribute
public static void Save(string fileName, Event e)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Event));

    using (Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
    {

        xmlSerializer.Serialize(stream, e);
    }
}
public static Event Load(string fileName)
{
    Event e = null;
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Event));

    using (Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read,  FileShare.None))
    {

        e = (Event)xmlSerializer.Deserialize(stream);
    }

    return e;
}
<?xml version="1.0"?>
<Event xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <id>1</id>
  <title>AA</title>
  <Start>2019-12-01T14:13:58.863</Start>
  <End>2019-12-01T15:13:58.787</End>
  <contacts>
    <Contact>
      <Id>1</Id>
      <Name>ABC</Name>
    </Contact>
    <Contact>
      <Id>2</Id>
      <Name>ABCD</Name>
    </Contact>
    <Contact>
      <Id>3</Id>
      <Name>ABCDE</Name>
    </Contact>
  </contacts>
</Event>
<?xml version="1.0" encoding="UTF-8"?>
<Events>
    <Event>
        <id>1</id>
        <title>AA</title>
        <start>2019-12-01T14:13:58.863</start>
        <end>2019-12-01T15:13:58.787</end>
        <contacts>
            <contact>
                <id>1</id>
                <name>ABC</name>
            </contact>
            <contact>
                <id>2</id>
                <name>ABCD</name>
            </contact>
            <contact>
                <id>3</id>
                <name>ABCDE</name>
            </contact>
        </contacts>
    </Event>
    <Event>
        <id>2</id>
        <title>AA</title>
        <start>2019-12-02T14:13:58.863</start>
        <end>2019-12-02T15:13:58.787</end>
        <contacts>
            <contact>
                <id>4</id>
                <name>DEF</name>
            </contact>
            <contact>
                <id>5</id>
                <name>BNH</name>
            </contact>
            <contact>
                <id>6</id>
                <name>KLK</name>
            </contact>
        </contacts>
    </Event>
</Events>
[XmlType("Event")]
public class Event
{
    [XmlElement("id")]
    public string Id { get; set; }
    [XmlElement("title")]
    public string Title { get; set; }
    [XmlElement("start")]
    public DateTime Start { get; set; }
    [XmlElement("end")]
    public DateTime End { get; set; }
    [XmlArray("contacts")]
    public virtual List<Contact> Contacts { get; set; }
}

[XmlType("contact")]
public class Contact
{
    [XmlElement("id")]
    public int Id { get; set; }

    [XmlElement("name")]
    public string Name { get; set; }
}
using (var reader = new StreamReader(filename))
{
    var deserializer = new XmlSerializer(typeof(List<Event>), new XmlRootAttribute("Events"));
    return (List<Event>) deserializer.Deserialize(reader);
}
var outputDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var filename = Path.Combine(outputDirectory, @"events.xml");