如何将 xml 字符串反序列化为一组 C# 类 而不必仅为 xml 属性声明大量属性?
How to deserialize a xml string to a set of C# classes without having to declare a lot properties just for xml attributes?
我有下面的 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>
您应该能够使用 ExpandoObject(System.Dynamic 的一部分)。
我自己尝试了一个快速解决方案,并且能够将 xml 成功解析为动态对象。
您需要做的是:
将字符串数据解析为 XDocument,这样您就有了一个 xml 文档对象。
var doc = XDocument.Parse(xmlData);
然后我将文档转换为 json 字符串,您不需要这样做,但这是我测试是否可行的最快方法。
(为此我需要添加 Newtonsoft.Json NuGet 包。)
string jsonText = JsonConvert.SerializeXNode(doc);
最后我反序列化了这个对象:
dynamic dyn = JsonConvert.DeserializeObject<<strong>ExpandoObject</strong>>(jsonText);
我喜欢使用 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; }
}
}
我有下面的 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>
您应该能够使用 ExpandoObject(System.Dynamic 的一部分)。
我自己尝试了一个快速解决方案,并且能够将 xml 成功解析为动态对象。
您需要做的是:
将字符串数据解析为 XDocument,这样您就有了一个 xml 文档对象。
var doc = XDocument.Parse(xmlData);
然后我将文档转换为 json 字符串,您不需要这样做,但这是我测试是否可行的最快方法。 (为此我需要添加 Newtonsoft.Json NuGet 包。)
string jsonText = JsonConvert.SerializeXNode(doc);
最后我反序列化了这个对象:
dynamic dyn = JsonConvert.DeserializeObject<<strong>ExpandoObject</strong>>(jsonText);
我喜欢使用 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; }
}
}