【问题标题】:how to convert xml to list of objects如何将xml转换为对象列表
【发布时间】:2017-11-07 12:47:33
【问题描述】:

这是我的目标是遍历所有节点的代码,而不仅仅是一个节点,所以在我的情况下,它会同时获得第一个设备节点和他的所有子节点,所以我如何才能获得每个设备和 PortA PortB 节点。然后我就可以设置我的班级值了。

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

这是我的 XML 文件,看起来需要获取每个设备元素及其自己的值并设置为我的类值。

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

【问题讨论】:

  • 我不确定你想在这里实现什么。您是否需要帮助构建一个递归方法,该方法将使用 xml 中列出的层次结构完全实例化 Device 对象? Device 类是什么样的,我们可以看到那里的代码吗?请编辑问题以更具体地说明您需要帮助的内容以及您已经尝试过的内容。

标签: c# xml xmlserializer xelement xattribute


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    Xml 序列化也许能做你想做的事。不确定您的最终结果需要是什么。您可以使用下面的类来简单地读取 xml 数据,然后从结果中创建您需要的对象。

    创建类。

    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
    }
    

    然后你可以使用这个函数从一个字符串反序列化:

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

    这样使用:

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

    obj 然后将是您的 xml 数据中完全填充的对象。如果这是你想要的,我可以填补上面的空白。

    【讨论】:

      【解决方案3】:

      我喜欢使用递归算法:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 2014-07-07
        • 2010-09-29
        相关资源
        最近更新 更多