Linq XML to Object,其中 xml 节点具有嵌套元素
Posted
技术标签:
【中文标题】Linq XML to Object,其中 xml 节点具有嵌套元素【英文标题】:Linq XML to Object, where xml nodes have nested elements 【发布时间】:2019-12-01 11:15:27 【问题描述】:我需要从 XML 文档生成一个List<Event>
,而Event
有一个List<Contact>
。阅读时如何将 XML 转换为 List<Event>
对象:
这是我的事件类:
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;
联系班级
public class Contact
public int Id get; set;
public string Name 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>
获取我使用的 XML 文档
XDocument xml = new XDocument();
xmlDoc = XDocument.Load("Data.xml");
我对如何将项目读取到列表中感到震惊。我该怎么做?
【问题讨论】:
可以反序列化xml:docs.microsoft.com/en-us/dotnet/api/… 【参考方案1】:假设你的 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>
您可以定义以下两个代表 XML 文档结构的类:
[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;
然后你可以反序列化你的 XML 如下:
using (var reader = new StreamReader(filename))
var deserializer = new XmlSerializer(typeof(List<Event>), new XmlRootAttribute("Events"));
return (List<Event>) deserializer.Deserialize(reader);
您必须将filename
替换为您的xml 文件所在的路径。
如果我们假设您已选择要复制到输出目录的 xml - 右键单击文件并检查它的属性以检查或设置它 - 那么您可以很容易地获得它的路径,如下所示(假设它被称为 events.xml):
var outputDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var filename = Path.Combine(outputDirectory, @"events.xml");
为了让您掌握 XmlSerializer,我建议您从 XmlSerializer 开始,然后继续使用此 Examples of XML Serialization。
【讨论】:
嗨,这很有效,感谢您提供的链接,我会检查一下,我是 c# 新手,一切看起来都很奇怪。 我可以用同样的方法从 xml 文件中获取特定节点并更新并保存它 @mikeoconner 非常欢迎您。我很高兴能帮上忙。 @mikeoconner 如果我必须得到一个特定的节点,更新它并保存它,我会选择 LINQ to XML。您可以从docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… 开始阅读。然后查看类似***.com/questions/1487653/… 的答案或查看教程,它们很多。如果您需要任何具体的帮助。请提出另一个问题,具体说明问题所在。谢谢【参考方案2】:使用System.Xml.Serialization
将Event
对象保存到XML 或从XML 加载。将创建的 XML 格式与您的非常相似。
可以用相同的方式保存/加载List<Event>
(在下面的示例中,Event
需要替换为List<Event>
)。
注意:以下示例中的加载(使用XmlSerializer.Deserialize
)将无法与您创建的 XML 文件一起正常工作,它仅适用于保存示例创建的 XML 文件(使用 @ 987654332@)。要将XmlSerializer.Deserialize
与您自己的XML 文件一起使用,需要将XmlElement
属性添加到类属性并为XmlSerializer
提供XmlRootAttribute
(如Christos answer)。如果您可以使用XmlSerializer.Serialize
创建 XML 文件而不使用您已经创建的文件,您将节省额外的工作。
将Event
对象保存为 XML(序列化)的示例:
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);
从 XML 加载 Event
对象的示例(脱盐):
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;
将为 Event
对象创建的 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>
【讨论】:
我尝试了这种方法,第一次它给了我一个错误,说不需要 RootTag。然后我在***上找到了一个答案,说要初始化像 XmlSerializer xmlSerializer = new XmlSerializer(typeof(ListxmlSerializer.Deserialize
的默认操作无法正确处理您的文件。我在答案中的意思是建议您首先使用XmlSerializer.Serialize
创建XML 文件,这样您的对象将以默认方式序列化为XML,xmlSerializer.Deserialize
将正常工作。如果要使用已创建的文件,则必须使用 XmlElement
属性,例如 Christos answer
您需要像Christos 一样提供XmlRootAttribute
答案。如果您首先使用XmlSerializer.Serialize
创建文件,那么您的工作量会更少,不需要XmlElement
属性和XmlRootAttribute
。以上是关于Linq XML to Object,其中 xml 节点具有嵌套元素的主要内容,如果未能解决你的问题,请参考以下文章