C# Linq XML to对象,其中XML节点具有嵌套元素
我需要从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转换为列表
对象:
这是我的活动课:
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");