【问题标题】:Converting XML to C# object将 XML 转换为 C# 对象
【发布时间】:2017-10-14 02:17:27
【问题描述】:

我需要从这些 xml 数据中获取 OrderID:

<?xml version="1.0" encoding="utf-8"?>
<GetOrdersResponse xmlns="urn:ebay:apis:eBLBaseComponents">
  <Timestamp>2015-12-10T16:12:55.184Z</Timestamp>
  <Ack>Success</Ack>
  <Version>967</Version>
  <Build>e967_core_Bundled_5642307_R1</Build>
  <OrderArray>
    <Order>
      <OrderID>865826</OrderID>
      <OrderStatus>Active</OrderStatus>
   </Order>
  </OrderArray>
</GetOrdersResponse>

这个我试过了,还是不行。

var xDoc = XDocument.Parse(xmlResult);
var orderElements = xDoc.Elements("GetOrdersResponse").Elements("OrderArray").Elements("Order");
foreach (XElement elem in orderElements)
{
    var orderId = Convert.ToInt32(_xmlHelper.GetChildElementValue(elem, "OrderID"));
}

请指教。

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    对于这样的问题,我总是会选择使用 XmlSerializer。 使用此类:

        using System;
        using System.Xml.Serialization;
        using System.Collections.Generic;
        namespace classes
        {
            [XmlType(Namespace = "urn:ebay:apis:eBLBaseComponents")]
       public class Order
        {
            public int OrderID { get; set; }
            public string OrderStatus { get; set; }
        }
    
        [XmlType(Namespace = "urn:ebay:apis:eBLBaseComponents")]
        public class OrderArray
        {
            public List<Order> Orders { get; set; }
        }
    
        [XmlRoot(Namespace = "urn:ebay:apis:eBLBaseComponents")]
        public class GetOrdersResponse
        {
            public string Timestamp { get; set; }
            public string Ack { get; set; }
            public string Version { get; set; }
            public string Build { get; set; }
            public OrderArray OrderArray { get; set; }
        }
    
        }
    

    然后反序列化到你的对象:

    XmlSerializer serializer = new XmlSerializer(typeof(GetOrdersResponse ));
    using (TextReader reader = new StringReader(xmlResult))
    {
        GetOrdersResponse result = (GetOrdersResponse) serializer.Deserialize(reader);
    }
    
    int id=result.OrderArray.Orders.First().OrderID; //this will return ID of first object in Orders list.
    

    【讨论】:

    • " [XmlAttribute(AttributeName = "xmlns")] public string Xmlns { get; set; }" 看起来非常非常错误......其中大部分应该是 XmlType,而不是 XmlRoot
    • fyi 它仍然比它需要的复杂得多 - XmlSerializer 做了很多合理的假设,例如“命名空间由子代继承”和“事物是像成员一样命名的元素” - 所以你只需要:gist.github.com/mgravell/1b91e0e5e6a47bdb3cff42e61281f6ce - 仅供参考
    • 嘿,对不起,但我喜欢你的回答(我喜欢 XmlSerializer),但如果我们假设 OrderArray 实际上是 0-1-or-many,你也会失去整个类型(OrderArray) 并在GetOrdersResponse 上使用public List&lt;Order&gt; OrderArray { get; set; }
    • 没错,但举一个例子,这不是必需的。但这应该实现,否则 OrderArray 将是多余的。
    • 最后,如果你使用public int OrderID { get; set; },正确的转换会自动发生
    【解决方案2】:

    你可以按照这个:

    XDocument xdoc = XDocument.Load("YourXMLFile");
    var orderId = xdoc.Descendants("OrderID").FirstOrDefault().Value;
    

    【讨论】:

      【解决方案3】:

      我不希望xDoc.Elements("GetOrdersResponse") 工作,因为这是在默认命名空间中查找,因为这里的所有内容都在"urn:ebay:apis:eBLBaseComponents" 中。因此,您需要至少通过XName 告诉它:

          var xDoc = XDocument.Parse(xmlResult);
          XNamespace ns = "urn:ebay:apis:eBLBaseComponents";
          var orderElements = xDoc.Elements(ns + "GetOrdersResponse")
                  .Elements(ns + "OrderArray").Elements(ns + "Order");
          foreach (XElement elem in orderElements)
          {
              var orderId = (int)elem.Element(ns + "OrderID");
          }
      

      (注意使用(int) 也可以进行特定于xml 的转换)

      但是,只使用XmlSerializer 并让担心解密数据可能会更容易。

      【讨论】:

        【解决方案4】:

        你应该使用这个示例代码

        重要提示

        • 序列化类标记为[Serializable] attirbute
        • 如果类名与 xml 根标签不同,则类名 标记为[XmlRoot(ElementName = "XmlTagName")]属性
        • 如果序列化类的属性类型为另一个类,则此 属性标记为 [XmlElement("XmlTagName")] 属性

        示例代码

        型号

              [Serializable]
                [XmlRoot(ElementName = "HardwareInfo")]
                public class Hardware
                {
                    [XmlElement]
                    public string cpu_name { get; set; }
                    [XmlElement]
                    public int ram_size { get; set; }
        
                    [XmlElement("hard_disk")]
                    public List<HardDisk> hd { get; set; }                   
                }
        
                [Serializable]
                [XmlRoot(ElementName = "hard_disk")]
                public class HardDisk
                {
                    [XmlElement]
                    public string model { get; set; }
                    [XmlElement]
                    public string size { get; set; }
                }
        
        namespace ConsoleApplication1
        {
            class Program
            {
                static void Main(string[] args)
                {
                    string xmlString = @"<HardwareInfo>
                                          <cpu_name> ABC Pentium xyz</cpu_name>
                                          <ram_size> 123 </ram_size>
                                          <hard_disk>
                                            <model>Toshiba XYZ</model>
                                            <size> 123 GB </size>
                                          </hard_disk>
                                          <hard_disk>
                                            <model>Logitech XYZ</model>
                                            <size> 99 GB </size>
                                          </hard_disk>
                                        </HardwareInfo>";
        
                    var result = DeSerialization<Hardware>(xmlString);
                }
        
                static T DeSerialization<T>(string xmlStrig) where T : class
                {
                    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));                        
                    using (StringReader sReader = new StringReader(xmlStrig))
                    {
                        return (T)xmlSerializer.Deserialize(sReader);
                    }
                }
            }          
        }
        

        【讨论】:

        • 对不起,但这只是......没有帮助; XmlSerializer关心[Serializable] - 一点也不。问题中主要的复杂因素是命名空间,这个答案没有解决;并且:它甚至不是特定于问题的......
        【解决方案5】:

        您也可以使用XmlDocumentXmlNodeList 获取它 - 如果您将 xml 数据保存在文件中

                XmlDocument doc = new XmlDocument();
                doc.Load("your XML File Name with extension");
                XmlNodeList elemList = doc.GetElementsByTagName("OrderID");
                for (int i = 0; i < elemList.Count; i++)
                {
                    Console.WriteLine(elemList[i].InnerText);
                }
        

        【讨论】:

        • 这会起作用,但GetElementsByTagName 几乎总是对任何问题的糟糕解决方案 - 极易出错等。问题中的主要并发症是命名空间,可以通过常规完美解决XDocumentXmlDocument的查询方法,不需要GetElementsByTagName的核选项
        猜你喜欢
        • 1970-01-01
        • 2012-10-21
        • 2014-07-07
        • 1970-01-01
        • 2013-07-13
        • 2018-11-27
        • 2020-09-29
        • 2017-05-27
        • 1970-01-01
        相关资源
        最近更新 更多