从动态XML转换为C#对象

6
我可以帮助您进行翻译。以下是需要翻译的内容:

我需要输入将动态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中的动态和ExpandoObject,这种方法可以通过使用键来动态获取值。但是我不知道如何将它们填充到我的数据模型中。
注意:我不想定义这个类模型结构,因为随着时间的推移会发生变化。我正在寻找一种解决方案,可以像DynamicObject.Addresses.Address [0] .City一样获取值。
请提供您的意见。

2
什么是“动态XML”?你尝试过例如LinqToXml吗? - mipe34
我不想持续跟踪XML内容,因为它经常发生变化。我的数据模型也应该根据运行时输入的XML动态变化。 - KRP
我尝试过使用Linq to Xml,但无法处理元素数组,例如:addresses。 - KRP
为什么不使用XPath查询(LINQ)您的XML?http://msdn.microsoft.com/en-us/library/bb387057.aspx - Adolfo Perez
1
我个人认为,使用动态对象与定义一些类相比,并没有更好的优势。如果/当数据源发生变化时,您仍然需要重构代码。如果您有类,使用重构工具进行重构会更容易。但这只是我的个人看法。 - BlakeH
显示剩余2条评论
5个回答

6
使用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

4

3
请不要添加仅包含链接的答案,因为一旦链接失效,它们就变得无用了。请在您的答案中添加相关内容,并使用链接进行引用。请注意,此翻译可能根据上下文略有不同:请勿添加仅包含链接的答案,因为如果链接失效,它们将变得无用。请在你的回答中添加相关内容,并提供链接引用。 - Ren

2

请看这个例子:

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

您将获得:<City>莫斯科</City> 或者使用DynamicObject的解决方案如下:
    XElement root = XElement.Parse(xml);
    dynamic persons = DynamicXml.Parse(xml);
    Console.WriteLine(persons.Person.Addresses.Address[1].City);

使用动态方法将XML反序列化为对象


1

请不要添加仅包含链接的答案,因为如果链接失效,它们将变得无用。请在此处添加相关内容,并使用链接进行引用。 - Ren

0

我为了这个目的创建了一个项目,因为我对其他替代方案(如其他答案中链接到的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'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接