【问题标题】:convert from dynamic xml to c# object从动态 xml 转换为 c# 对象
【发布时间】:2013-05-15 00:26:22
【问题描述】:

在将动态 xml 转换为已定义的 c# 对象模型时需要输入

我的示例 xml 如下:

<?xml version="1.0" encoding="utf-8" ?>
  <Persons>
    <Person>
      <Id>10</Id>
      <FirstName> Dino </FirstName>
      <LastName> Esposito </LastName>
      <Addresses>
        <Address>
          <AddressType>BillTo</AddressType>
          <Street1></Street1>
          <Street2></Street2>
          <Street3></Street3>
          <City>Moscow</City>
        </Address>
        <Address>
          <AddressType>ShipTo</AddressType>
          <Street1></Street1>
          <Street2></Street2>
          <Street3></Street3>
          <City>Moscow</City>
        </Address>
        <Address>
          <AddressType>Contact</AddressType>
          <Street1></Street1>
          <Street2></Street2>
          <Street3></Street3>
          <City>Moscow</City>
        </Address>
      </Addresses>
    </Person>
  </Persons>

我希望在运行时将此 xml 的值转换为 C# 对象。 我希望定义一个类似于以下内容的对象: 我的预期类对象 C# 如下:

public class Person
{
    public int Id { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public IList<Address> Addresses { get; set; }
}

public class Address
{
    public string AddressType { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string Street3 { get; set; }
    public string City { get; set; }
}

我在 C# 4.0 中使用了 dynamic 和 ExpandoObject,这种方法允许我通过使用键来动态获取值。我不知道如何将这些填充到我的数据模型中。

注意:我不想定义这个类模型结构,这会随着时间的推移不断变化。我正在寻找一种解决方案,它允许我获取 DynamicObject.Addresses.Address[0].City 之类的值。

请提供您的意见。

【问题讨论】:

  • 什么是“动态xml”?你试过吗? LinqToXml?
  • 我不想关注 xml 内容,这一直在变化。我的数据模型也应该根据运行时的输入 xml 动态变化。
  • 我已经尝试过 linq to Xml,我无法使用元素数组。例如:地址
  • 为什么不使用 XPath 查询 (LINQ) XML? msdn.microsoft.com/en-us/library/bb387057.aspx
  • 我个人看不出使用动态对象比定义一些类更好。如果/当数据源发生变化时,您无论如何都必须重构代码。如果你有类,那么使用重构工具更容易做到这一点。但这只是我的 2 美分。

标签: c# .net c#-4.0 dynamic expandoobject


【解决方案1】:

使用 LINQ2XML 的解决方案可能如下所示(不需要类):

var xml = XDocument.Parse(xmlSrc); // from XML string, e.g.: <xml ...><Persons><Person>...
//var xml = XDocument.Load(xmlFile); // from XML file, e.g.: c:\temp\persons.xml

var persons = xml.Root.Elements("Person").ToList();
var p1Addresses = persons[0].Elements("Addresses").ToList();
foreach (var address in p1Addresses.Elements("Address"))
{
    var elementAddress = address.Element("AddressType");
    var elementCity = address.Element("City");
    System.Console.WriteLine(string.Format("{0} - {1}", elementAddress.Value, elementCity.Value));
}

输出是:

BillTo - Moscow
ShipTo - Moscow
Contact - Moscow

【讨论】:

    【解决方案2】:

    我建议您阅读这篇文章:http://www.codeproject.com/Articles/62839/Adventures-with-C-4-0-dynamic-ExpandoObject-Elasti。有一种方法可以从 XML 构造动态对象。 或者这篇文章:http://www.codeproject.com/Articles/461677/Creating-a-dynamic-object-from-XML-using-ExpandoOb。随心所欲,您可以根据需要自定义代码。

    【讨论】:

    • 请不要添加仅链接的答案,因为如果链接断开,它们将变得无用。请在此处将相关内容添加到您的答案中,并通过链接进行引用。
    【解决方案3】:

    检查这个例子:

            string xml =
                @"<?xml version='1.0' encoding='utf-8' ?>
                  <Persons>
                   <Person>
                    <Id>10</Id>
                    <FirstName> Dino </FirstName>
                    <LastName> Esposito </LastName>
                    <Addresses>
                      <Address>
                       <AddressType>BillTo</AddressType>
                       <Street1></Street1>
                       <Street2></Street2>
                       <Street3></Street3>
                       <City>Moscow</City>
                    </Address>
                    <Address>
                     <AddressType>ShipTo</AddressType>
                     <Street1></Street1>
                     <Street2></Street2>
                     <Street3></Street3>
                     <City>Moscow</City>
                    </Address>
                    <Address>
                      <AddressType>Contact</AddressType>
                      <Street1></Street1>
                      <Street2></Street2>
                      <Street3></Street3>
                      <City>Moscow</City>
                    </Address>
                 </Addresses>
                </Person>
               </Persons>";
    
            XElement root = XElement.Parse(xml);
    
            IEnumerable<XElement> list = root.XPathSelectElements("./Person/Addresses/Address[2]/City");
            foreach (XElement el in list)
                Console.WriteLine(el);
            Console.ReadLine();
    

    你会得到:&lt;City&gt;Moscow&lt;/City&gt;

    或者使用DynamicObject查看这个解决方案:

        XElement root = XElement.Parse(xml);
        dynamic persons = DynamicXml.Parse(xml);
        Console.WriteLine(persons.Person.Addresses.Address[1].City);
    

    Deserialize XML To Object using Dynamic

    【讨论】:

      【解决方案4】:

      感谢大家的投入,我正在寻找的解决方案可在此位置找到 http://www.codeproject.com/Tips/227139/Converting-XML-to-an-dynamic-object-using-ExpandoO.

      【讨论】:

      • 请不要添加仅链接的答案,因为如果链接断开,它们将变得无用。请在此处将相关内容添加到您的答案中,并通过链接进行引用。
      【解决方案5】:

      我专门为此目的创建了一个项目,因为我对替代方案不满意(例如其他答案中链接到的 CodeProject 文章)。

      我已经在 Github 上发布了:https://github.com/jonathanconway/XmlToDynamic

      我宁愿不在这里发布源代码,因为它太大了,但是这里是用法:

      var xmlString =
          @"<addressBook>
             <contacts>
               <contact>
                 <name>Jonathan</name>
               </contact>
             </contacts>
           </addressBook>";
      var dynamicXml = XElement.Parse(xmlString).ToDynamic();
      var firstPersonsName = dynamicXml.contacts[0].name.Value;
      // firstPersonsName will be 'Jonathan'
      

      【讨论】:

        猜你喜欢
        • 2012-10-21
        • 1970-01-01
        • 2011-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-02
        • 1970-01-01
        相关资源
        最近更新 更多