C# 将 XML 解析为带有子元素的对象

Posted

技术标签:

【中文标题】C# 将 XML 解析为带有子元素的对象【英文标题】:C# Parse XML into Object with child elements 【发布时间】:2017-10-14 00:19:21 【问题描述】:

我正在尝试将 XML 文件读入 C# 对象。 XML 包含多个子元素。使用下面的代码,我可以毫无问题地访问所有顶部字段(版本、实时、pageid 等),但是当我尝试访问子节点值时,我收到一个

Object reference not set to an instance of an object.

我认为这表明 XMLSerializer 无法将节点与我的对象匹配。我尝试了不同的对象类型,例如数组上的 List 字段,但似乎仍然得到相同的结果,所以我不确定解决这个问题的最佳方法是什么?

任何为我指明正确方向的帮助将不胜感激。

XML

<?xml version="1.0" encoding="utf-8"?>
  <LiveModelStruct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <version>1</version>
   <live>true</live>
   <pageid>1</pageid>
   <data>test data</data>
   <giveawayactive>false</giveawayactive>
   <giveawayserial>00000000</giveawayserial>
   <templates>
     <template>
       <id>1</id>
       <title>Template 1</title>
       <type>Opener</type>
     </template>
     <template>
       <id>2</id>
       <title>Template 2</title>
       <type>Song</type>
     </template>
  </templates>
 </LiveModelStruct>

对象

[XmlRoot(ElementName = "LiveModelStruct")]
public class LiveModelStruct

    [XmlElement(ElementName = "version")]
    public string version  get; set; 
    [XmlElement(ElementName = "live")]
    public string live  get; set; 
    [XmlElement(ElementName = "pageid")]
    public string pageid  get; set; 
    [XmlElement(ElementName = "data")]
    public string data  get; set; 
    [XmlElement(ElementName = "giveawayactive")]
    public string giveawayactive  get; set; 
    [XmlElement(ElementName = "giveawayserial")]
    public string giveawayserial  get; set; 
    [XmlElement(ElementName = "templates")]
    public Templates Templates  get; set; 
    [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Xsi  get; set; 
    [XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Xsd  get; set;  


[XmlRoot(ElementName = "templates")]
public class Templates

    [XmlElement(ElementName = "template")]
    public Template[] Template  get; set;     


[XmlRoot(ElementName = "template")]
public class Template

    [XmlElement(ElementName = "id")]
    public string id  get; set; 
    [XmlElement(ElementName = "title")]
    public string title  get; set; 
    [XmlElement(ElementName = "type")]
    public string type  get; set; 

代码

...
var serializer = new XmlSerializer(typeof(LiveModelStruct));
var data = (LiveModelStruct)serializer.Deserialize(stream);
var test1 = data.version;
Debug.WriteLine(test1); //Returns 1 as it should

var test = data.Templates.Template[0].title; //Throws Error
Debug.WriteLine(test);

【问题讨论】:

使用 LINQ to XML 我看不出代码有什么问题。我将所有内容粘贴到 LinqPad 中并运行它,它给了我 1 和模板 1,没有例外。 我在这里做了一个dotnetfiddle:dotnetfiddle.net/kDv4nF,它也可以工作。 @PalleDue - 我想知道使用 Xamarin 是否会导致它无法正常工作.. :/ 【参考方案1】:

使用 LINQ to XML 解析您的 XML。

Parse xml using LINQ to XML to class objects

XDocument doc = XDocument.Parse(xml);
var result = from c in doc.Descendants("LiveModelStruct")
             select new LiveModelStruct()
             
                    version = (string)c.Element("version").Value,
                    live = (string)c.Element("live").Value
             ;

【讨论】:

我正在尝试实现这一点,但收到一个语法错误说明:找不到源类型“XDocument”的查询模式的实现。找不到“选择”。我添加了对 System.Linq 和 System.Xml.Linq 的引用。 好的,我用 doc.Descendants("LiveModelStruct") 解决了上述问题 @logicallysynced 如果您的问题已解决,请尽可能标记为已解决。 最后我使用 JSON over XML 来解决这个问题,因为我认为 Xamarin 导致 LINQ 和我自己的代码出现问题(这在普通的 .NET 应用程序中显然工作正常)。 @logicallysynced 不错的选择。除非您需要 XML 可以做而 JSON 做不到的事情,否则 XML 使用起来会更复杂。使用 JSON.NET 轻松序列化和反序列化对象。

以上是关于C# 将 XML 解析为带有子元素的对象的主要内容,如果未能解决你的问题,请参考以下文章

Python将XML解析为缺少元素的CSV

Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素

Oracle XML 解析表多个子元素

C# xml 反序列化不会将子元素提取到列表中

C# LINQ-to-XML 选择子元素属性最大的元素

带有子元素的 Android 自定义可展开/可折叠视图