[英]Deserialize XML Response with Incremented Element Names in C#
我正在尝试使用 ASP.NET C# 使用 3rd 方 API,该 API 返回结果,如下面的示例所示,并且我对子对象具有递增名称的事实感到困惑:
<Results>
<Count>3</Count>
<Result1>
<Id>1</Id>
<Property1>value</Property1>
<Property2>value</Property2>
...
<PropertyN>value</PropertyN>
</Result1>
<Result2>...properties...</Result2>
<Result3>...properties...</Result3>
</Results>
我的 C# 类如下所述,通过一些研究,我假设我必须实现IXmlSerializable
以某种方式处理这个:
public class Results : IXmlSerializable
{
[XmlElement("Count")]
public int Count { get; set; }
public List<Result> ResultItems { get; set; }
}
这是 XML 的常见模式吗?有人对如何序列化它有任何想法吗? 我很少使用 XML(主要是 JSON),所以提前致谢。
使用 xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication42
{
class Program
{
static void Main(string[] args)
{
string xml =
"<Root>" +
"<Results>" +
"<Count>3</Count>" +
"<Result1>...properties...</Result1>" +
"<Result2>...properties...</Result2>" +
"<Result3>...properties...</Result3>" +
"</Results>" +
"</Root>";
XElement xResults = XElement.Parse(xml);
Results results = xResults.Elements("Results").Select(x => new Results() {
Count = (int)x.Element("Count"),
ResultItems = x.Elements().Where(y => y.Name.LocalName.StartsWith("Result")).Select(y => (string)y).ToList()
}).FirstOrDefault();
}
}
public class Results
{
public int Count { get; set; }
public List<string> ResultItems { get; set; }
}
}
jdweng 的回答有效,对于那些可以选择使用的人来说,应该接受它; 但是,我的问题是数据在一个更大的 XML 响应中,并且使用 xml 序列化程序而不是XElement
可以很好地处理 95% 的字段(另外 5% 是我在问题中指定的部分),所以我不我不想放弃该代码 - 相反,我想实现 IXmlSerializable 接口。
在撕掉了我的大部分头发并从本文中获得了一些帮助后,我终于想出了如何为我的情况实现IXmlSerializable
,我想为任何有类似问题的人发布答案,以及社区反馈,因为没有似乎没有关于堆栈溢出的任何内容:
public class Results : IXmlSerializable
{
public int Count { get; set; }
public List<Result> ResultItems { get; set; }
public Results()
{
ResultItems = new List<Result>();
}
public XmlSchema GetSchema()
{
return (null);
}
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement("Results");
if(reader.Name == "Count")
{
Count = reader.ReadElementContentAsInt();
}
for (int i = Count; i > 0; i--)
{
var result = new Result();
reader.ReadStartElement("Result" + i);
result.Property1 = reader.ReadElementContentAsInt();
result.Property2 = reader.ReadElementContentAsString();
...
...
result.PropertyN = reader.ReadElementContentAsString();
ResultItems.Add(result);
}
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
//I don't ever need to write this to XML,
//so I'm not going to implement this
throw new NotImplementedException();
}
}
首先,我调用reader.ReadToElement()
并将元素名称放在那里。 当 reader 被传递给ReadXml
方法时,它位于请求结果的开头,因此您需要将它传递到要序列化的对象的开头。
然后,我读取了名称为 Count 的第一个元素。 我将值放在 Count 属性中,然后遍历所有结果。 需要注意的是,必须读取结果对象的每个属性,否则会出现异常。
最后,我阅读了结束标签并继续我的生活。 请让我知道您对此实现的看法,以及是否可以进行任何改进。
我无法弄清楚的一件事是,我有一个结果对象,而读者有一个我想使用的方法: reader.ReadElementContentAs(typeof(Result), null)
- 这样做似乎比阅读更好每个单独的节点,就像我在我的实现中所做的那样。 有谁知道这是怎么做到的吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.