【问题标题】:Complex XML to C# classes - how to deserialize them?复杂的 XML 到 C# 类 - 如何反序列化它们?
【发布时间】:2019-07-23 10:00:54
【问题描述】:

我的目标是从 XML 中提取数据。但是我有一些相当复杂的 XML,它们不容易转换为 C 语言类。

XML 如下所示:

<group.........>
  <suite....>
    <properties>
      <property name=....../>
    </properties>
    <suite type="test">
      <suite type="test1">
        <suite...>    
          <suite...>     
            <suite...>  
              <case id="1000" name="example"> 
                <properties>
                  <property ...../>    
                </properties>
              </case>
              <case.......>
                <properties>
                  <property ...../>      
                </properties>
              </case>
              <case>
                <properties>
                  <property .... />           
                </properties>
              </case>
            </suite>
          </suite>
        </suite>
      </suite>
    </suite>
  </suite>
</group>

我使用了一个在线的 xml to c sharp convert 来创建类,但它似乎不能正确处理 XML 结构。

更新:

XML 来自 NUNIT3。它是写入 XML 文档的 UNIT3 控制台的结果。

更新 2:

我可以使用以下代码提取数据 - 不知道是否有更优雅的解决方案:

XElement resultFile = XElement.Load($"{resultFilePathList}"); 
                var dataFromXML = (
                    from data in resultFile.Descendants("case")
                    select new
                    {
                        caseid = data.Attribute("id").Value,
                        name = data.Attribute("fullname").Value,
                        result = data.Attribute("result").Value,
                        duration = data.Attribute("duration").Value
                    }
                );

【问题讨论】:

  • 将 XML 复制到剪贴板,然后在 VS 中选择 Edit/Paste Special/Paste XML as classes。除了设计你的 XML 文件的人没有创建一个有效的文件。
  • @Neil 试过它创建了很多类,比如 suitesuitesute 和 suitesuite 等多个类
  • 除非你能让这个 XML 的创建者“做得更好”,否则你将不得不在 XmlReader csharp.net-tutorials.com/xml/… 的帮助下“手动”解析那个 XML
  • @Neil,XmlReader 是做什么用的?
  • 我会在 XmlReader 之前使用 LINQ-to-XMLXDocument

标签: c# xml deserialization


【解决方案1】:

查看这段代码,就这么简单

using System.Xml.Serialization;
using System.IO;
.......
StreamReader streamer = new StreamReader("yourgroup.xml");
XmlSerializer serializer = new XmlSerializer(typeof(group));
group x = (group)serializer.Deserialize(streamer);
streamer.Close();

你确实定义了你的类,就像这样

public class group {List<suite> suite;}
public class suite
{
   public List<suite> suite;
   public List<property> properties;
}

好的,如果您需要特定的处理,您可以添加额外的注释 例如,如果有“case”元素,则创建具有不同名称的类

public class xcase
{
    public String id;
    public String name;
    public Property[] properties;...
}
public class suite
{
    [XmlElement(ElementName = "case")]
    public xcase[] cases {get; set; } 
    ....
}

【讨论】:

  • 我的案例类有属性和子属性元素。我想我需要添加一个案例类。
  • @uba2012 添加它,但给一个不同的名称。看这篇文章docs.microsoft.com/en-us/dotnet/standard/serialization/…
  • @uba2012 请检查更新的答案,我提供了如何映射 元素的示例
  • 谢谢。我想我只需要一个套房,对吧?为什么我不能命名案例类案例?我不明白。我明天会试试你的解决方案,因为它似乎是一个更好的解决方案
  • @uba2012 您不能将类命名为“case”,因为“сase”是 C# 中的保留关键字。它已经用于 switch/case 块。您不能将您的课程命名为“class”、“if”、“else”、“public”等。
【解决方案2】:

尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication120
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement group = doc.Root;
            Suite rootSuite = new Suite();
            Suite.ReadXml(group, rootSuite);
        }

    }
    public class Suite
    {
        public List<Suite> suites { get; set; }
        public List<Case> cases { get; set; }
        public Dictionary<string, string> properties { get; set; }
        public string type { get; set; }

        public static void ReadXml(XElement xparentSuite, Suite parentSuite)
        {
            foreach (XElement xSuite in xparentSuite.Elements("suite"))
            {
                parentSuite.type = (string)xSuite.Attribute("type");
                if (parentSuite.suites == null) parentSuite.suites = new List<Suite>();
                Suite newSuite = new Suite();
                parentSuite.suites.Add(newSuite);
                XElement properties = xSuite.Element("properties");
                if (properties != null)
                {
                    parentSuite.properties = properties.Elements("property")
                        .GroupBy(x => (string)x.Attribute("name"), y => (string)y)
                        .ToDictionary(x => x.Key, y => y.FirstOrDefault());
                }
                parentSuite.cases = xSuite.Elements("case").Select(x => new Case(x)).ToList();
                ReadXml(xSuite, newSuite);
            }
        }
    }
    public class Case
    {
        public string id { get; set; }
        public string name { get; set; }
        public Dictionary<string, string> properties { get; set; }

        public Case() { }
        public Case(XElement _case)
        {
            id = (string)_case.Attribute("id");
            name = (string)_case.Attribute("name");
            properties = _case.Descendants("property")
                .GroupBy(x => (string)x.Attribute("name"), y => (string)y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

        }

    }

}

【讨论】:

  • 为什么Case不是一个类?
  • Case 可以是一个类。如果 case 只包含 KeyValuePair 我只是从发布的示例 xml 我虽然字典更简单。
  • 我用更新的 XML 更新了 OP。我正在尝试实现您的代码,但我想我需要先设计类?我需要 Suite 类(你提供的) 我需要 Case 类 我需要 properties 类 对吗?
  • 我更新了代码。如您所见,我喜欢使用字典。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-29
  • 2014-10-04
  • 1970-01-01
  • 2012-03-01
相关资源
最近更新 更多