代码之家  ›  专栏  ›  技术社区  ›  Natalie Perret

如何将XML字符串反序列化为一组C类,而不必只为XML属性声明许多属性?

  •  0
  • Natalie Perret  · 技术社区  · 6 年前

    下面是XML,我想知道如何将它反序列化为一组类,而不必为表示不同的XML属性(及其各自的值)而添加大量字段(到这些类中)。

    我想我可以在定义XML元素的顶级属性上使用一些支持声明性XML属性的.NET属性。

    <y:input xmlns:y='http://www.stuff.com/blahblah/42'>
        <y:datas>
            <y:instance yclass='Report' yid="report">
                <language yid='LANG_fr'/>
                <threshold>0.8</threshold>
                <typePeriod>predefinedPeriod</typePeriod>
                <interval>month</interval>
                <valuePeriod>April</valuePeriod>
                <fund yclass="Fund">
                    <name>K</name>
                    <performance yclass="Performance">
                        <typeValue>percent</typeValue>
                        <value>-0.05</value>
                    </performance>
                    [... lot of other fields ...]
                </fund>
            </y:instance>
        </y:datas>
    </y:input>
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Christo Nel    6 年前

    您应该能够使用expandoobject(system.dynamic的一部分)。

    我自己尝试了一个快速的解决方案,并且能够成功地将XML解析为动态对象。

    你需要做的是:

    1. 将字符串数据解析为xdocument,这样您就有了一个XML文档对象。

      var doc = XDocument.Parse(xmlData);

    2. 然后我将该文档转换为一个JSON字符串,您不需要这样做,但这是我测试这是否可行的最快方法。 (为此,我需要添加newtonsoft.json nuget包。)

      string jsonText = JsonConvert.SerializeXNode(doc);

    3. 最后,我对对象进行了如下反序列化:

      dynamic dyn = JsonConvert.DeserializeObject< ExpandoObject >(jsonText);

        2
  •  1
  •   jdweng    6 年前

    我喜欢使用XML LINQ和嵌套字典:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            const string FILENAME = @"c:\temp\test.xml";
            static void Main(string[] args)
            {
    
                XDocument doc = XDocument.Load(FILENAME);
                XNamespace yNs = doc.Root.GetNamespaceOfPrefix("y");
                Datas data = doc.Descendants(yNs + "datas").Select(x => new Datas() {
                    instances = x.Descendants(yNs + "instance").Select(y => new Instance() {
                        instance = (string)y.Attribute("yid"),
                        language = (string)y.Element("language").Attribute("yid"),
                        threshold = (decimal)y.Element("threshold"),
                        typePeriod = (string)y.Element("typePeriod"),
                        interval = (string)y.Element("interval"),
                        valuePeriod = (string)y.Element("valuePeriod"),
                        fund = y.Elements("fund").Select(z => new Fund() {
                            fields  = z.Elements().GroupBy(a => a.Name.LocalName, b => b.Elements()
                                .GroupBy(c => c.Name.LocalName, d => (string)d)
                                .ToDictionary(c => c.Key, d => d.FirstOrDefault()))
                                .ToDictionary(a => a.Key, b => b.FirstOrDefault())
                        }).FirstOrDefault()
                    }).ToList()
                }).FirstOrDefault();
            }
        }
        public class Datas
        {
            public List<Instance> instances { get; set; }
        }
        public class Instance
        {
            public string instance { get; set; }
            public string language { get; set; }
            public decimal threshold { get; set; }
            public string typePeriod { get; set; }
            public string interval { get; set; }
            public string valuePeriod { get; set; }
            public Fund fund { get; set; }
         }
        public class Fund
        {
            public Dictionary<string, Dictionary<string,string>> fields { get; set; }
        }
    }