uba2012
uba2012

Reputation: 385

Complex XML to C# classes - how to deserialize them?

My goal is to extract the data from the XML. But I have some rather complex XML that is not easily converted to C sharp classes.

The XML looks like this:

<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>

I have used an online xml to c sharp convert to create classes, but it does not seem to handle the XML structure correctly.

Update:

The XML comes from NUNIT3. It is the result of the UNIT3 console that is written to an XML document.

Update 2:

I am able to extract data using below code - don't know if there is a more elegant solution:

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
                    }
                );

Upvotes: 1

Views: 1477

Answers (2)

armagedescu
armagedescu

Reputation: 2156

Check this code, is as simple as this

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();

And you have do define your classes, somehow like this

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

Ok, you can add additional annotation if you need specific handling For instance if there is "case" element, create your class with different name

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

Upvotes: 1

jdweng
jdweng

Reputation: 34421

Try following :

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());

        }

    }

}

Upvotes: 1

Related Questions