简体   繁体   中英

how to convert xml to list of objects

Here is the code my goal is to iterate over all the nodes and not just one so in my case it gets the first Device Node and all his children at once so how can i get every single Device and PortA PortB nodes. then i will be able to set my class values.

private void loadXmlFile(string path)
{
    try
    {
        XElement deviceElement = XElement.Load(path);
        Device device = new Device();
        var allElements = deviceElement.DescendantNodes();
        foreach (var elm in deviceElement.Elements())
        {
            if (elm.Name == "Device")
            {
                foreach (XAttribute att in elm.Attributes())
                {
                    if (att.Name == "Type")
                    {
                        device.TBType1 = att.Value.ToString();
                    }
                    if (att.Name == "Name")
                    {
                        device.Name = att.Value.ToString();
                    }
                    if (att.Name == "ParentConnectedToPort")
                    {
                        device.ParentConnectedTo = att.Value.ToString();
                    }
                    if (att.Name == "DeviceConnectedToPort")
                    {
                        device.DeviceConnectedTo = att.Value.ToString();
                    }

                    string connectedTo = (string)elm.Parent.Attribute("Connected_BY");
                    if (att.Name == "properties" && connectedTo == "Directly")
                    {
                        string str = att.Value;
                        string[] parts = str.Split(':', ',');
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Here is my XML file looks like need to get every device element and its own values and set out to my class values .

<CMS>
  <Device Name="CM_HOST" Type="TR">
    <PortA Connected_BY="Directly">
      <Device TB="AR" ParentConnectedToPort="A" Name="Akitio" DeviceConnectedToPort="A" properties="{'Type': 'AR' ,'Name': 'Akitio','Cable': '20G Passive'}">
        <PortB Connected_BY="Directly">
          <Device TB="AR" ParentConnectedToPort="A" Name="doc1" DeviceConnectedToPort="B" properties="{'Type': 'AR' ,'Name': 'doc1','Cable': '20G Passive'}">
            <PortB Connected_BY="Directly">
              <Device TB="AR" ParentConnectedToPort="A" Name="doc2" DeviceConnectedToPort="B" properties="{'Type': 'AR' ,'Name': 'doc2','Cable': '20G Passive'}" />
            </PortB>
            <PortA Connected_BY="None" />
            <PortE Connected_BY="None" />
          </Device>
        </PortB>
        <PortA Connected_BY="None" />
        <PortE Connected_BY="None" />
      </Device>
    </PortA>
    <PortB Connected_BY="None" />
    <PortE Connected_BY="None" />
  </Device>
  <Sx properties="{'FTDI_port': '0' ,'SX_power_button_pin': '7','SX_SLP_S3_pin': '6','SX_SLP_S4_pin': '11','SX_SLP_S5_pin': '10','SX_TBT_wake_N_pin': '8','SX_PCIE_wake_pin': '9','G3_Power_Mode': 'PowerSplitter'}" />
</CMS>

使用XPath,您可以通过选择路径来选择节点列表。

Xml serialization may be able to do what you want. Not absolutely sure what your end result needs to be. You could use the classes below to simply read the xml data and then create the objects you need from the results.

Create the classes.

public class CMS
{
    [XmlElement("Device")]
    List<Device> Devices {get;set;}

    //other properties here...
}

public class Device
{
    public Port PortA { get;set;}
    public Port PortB { get;set;}
    public Port PortC { get;set;}
    public Port PortD { get;set;}
    public Port PortE { get;set;}

    //other properties here...TB, ParentConnectedToPort etc
}

public class Port
{
    public Device Device { get; set; }


    //other properties here...Connected_BY etc
}

Then you can use this function to deserialize from a string:

    public static T DeserializeXml<T>(string str)
    {
        var serializer = new XmlSerializer(typeof(T));
        object result;

        using (TextReader reader = new StringReader(str))
        {
            result = serializer.Deserialize(reader);
        }

        return (T) result;
    }

Used thus:

var s = "--your xml string--";
var obj = Deserialize<CMS>(s);

obj will then be a fully populated object from your xml data. If this is the kind of thing you want I can fill in the gaps above.

I like using a recursive algorithm :

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



namespace ConsoleApplication13
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement cms = doc.Descendants("CMS").FirstOrDefault();
            XElement device = cms.Element("Device");

            Device.RecursiveParseXml(device, Device.root);

        }

    }
    public class Device
    {

        public static Device root = new Device();

        public List<Port> ports { get; set; }

        public string name { get; set; }
        public string type { get; set; }
        public string tb { get; set; }
        public string deviceConnectedToPort { get; set; }
        public Dictionary<string, string> properties { get; set; }

        public static void RecursiveParseXml(XElement parent, Device device)
        {
            device.name = (string)parent.Attribute("Name");
            device.type = (string)parent.Attribute("Type");
            device.tb = (string)parent.Attribute("TB");
            device.deviceConnectedToPort = (string)parent.Attribute("DeviceConnectedToPort");
            string strProperties = (string)parent.Attribute("properties");
            if (strProperties != null)
            {
                string[] propertyArray = strProperties.Split(new char[] { ',', '{', '}' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
                string pattern = @"'(?'name'[^']+)':\s+'(?'value'[^']+)";
                device.properties = new Dictionary<string, string>();
                foreach (string property in propertyArray)
                {
                    Match match = Regex.Match(property, pattern);

                    device.properties.Add(match.Groups["name"].Value, match.Groups["value"].Value);
                }

            }
            foreach (XElement element in parent.Elements())
            {
                Port newPort = new Port();
                if (device.ports == null)
                {
                    device.ports = new List<Port>();
                }
                device.ports.Add(newPort);

                newPort.connectBy = (string)element.Attribute("Connected_BY");

                XElement newDevice = element.Element("Device");
                if (newDevice != null)
                {
                    newPort.device = new Device();
                    RecursiveParseXml(element.Element("Device"), newPort.device);
                }
            }
        }
    }
    public class Port
    {
        public string name { get; set; }
        public string connectBy { get; set; }
        public Device device { get; set; }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM