反序列化动态 XML
本文关键字:XML 动态 反序列化 | 更新日期: 2023-09-27 18:35:44
下面的XML
总是以这种格式出现,但<Hit>
节点下的元素是动态的,每次的名称或项目数可能不同。是否可以动态获取<Hit>
节点下的元素。
<SearchResponse>
<Response>
<Qtime>3</Qtime>
<HitsPerPage>10</HitsPerPage>
</Response>
<HitsCount>
<total>33</total>
<start>0</start>
<end>10</end>
</HitsCount>
<Hits>
<Hit>
<id type=''>123</id>
<eid type=''>456</eid>
<Title type='t'>
<![CDATA[title goes here]]>
</Title>
</Hit>
<Hit>
<id type=''>123</id>
<oid type=''>456</oid>
<Title type='t'>
<![CDATA[title goes here]]>
</Title>
<Description type='s'>
<![CDATA[Description goes here]]>
</Description>
</Hit>
</Hits>
</SearchResponse>
编辑:这是 C# 代码,它工作正常并从 <Hit>
节点获取 id,因为我已经定义了属性,但我需要让所有这些代码都动态起来。
[XmlRoot("SearchResponse")]
public sealed class SearchResponse {
[XmlElement("Response", Type = typeof(Response))]
public Response[] Responses { get; set; }
[XmlElement("HitsCount", Type = typeof(HitsCount))]
public HitsCount[] HitsCount { get; set; }
[XmlElement("Hits", Type = typeof(Hits))]
public Hits[] Hits { get; set; }
public static SearchResponse GetSearchResponseObject(string xmlString) {
try {
var reader = new StringReader(xmlString);
var serializer = new XmlSerializer(typeof(SearchResponse));
var instance = (SearchResponse)serializer.Deserialize(reader);
return instance;
} catch (Exception ex) {
var asd = ex.Message;
return null;
}
}
}
[Serializable]
public class Response {
[XmlElement("Qtime")]
public string Qtime { get; set; }
[XmlElement("HitsPerPage")]
public string HitsPerPage { get; set; }
}
[Serializable]
public class HitsCount {
[XmlElement("total")]
public string Total { get; set; }
[XmlElement("start")]
public string Start { get; set; }
[XmlElement("end")]
public string End { get; set; }
}
[Serializable]
public class Hits {
[XmlElement("Hit")]
public Hit[] Hit { get; set; }
}
[Serializable]
public class Hit {
[XmlElement("id")]
public string Id { get; set; }
}
编辑 2://点击类代码
public class Hit {
// Since "id" is expected in the XML, deserialize it explicitly.
[XmlElement("id")]
public string Id { get; set; }
private readonly List<XElement> _elements = new List<XElement>();
[XmlAnyElement]
public List<XElement> Elements { get { return _elements; } }
}
由于您不知道Hit
类中可能存在哪些元素,因此可以将 List<XElement>
属性添加到类中,并将 [XmlAnyElement]
属性附加到该类。 然后,它将捕获类的 XML 中的任何和所有未知元素。 反序列化元素后,可以添加 API 属性来查询具有特定名称的元素,例如:
public class Hit
{
// Since "id" is expected in the XML, deserialize it explicitly.
[XmlElement("id")]
public string Id { get; set; }
private readonly List<XElement> elements = new List<XElement>();
[XmlAnyElement]
public List<XElement> Elements { get { return elements; } }
#region convenience methods
public string this[XName name]
{
get
{
return Elements.Where(e => e.Name == name).Select(e => e.Value).FirstOrDefault();
}
set
{
var element = Elements.Where(e => e.Name == name).FirstOrDefault();
if (element == null)
Elements.Add(element = new XElement(name));
element.Value = value;
}
}
const string title = "Title";
[XmlIgnore]
public string Title
{
get
{
return this[title];
}
set
{
this[title] = value;
}
}
#endregion
}
顺便说一下,如果你用 [XmlArray]
而不是 [XmlElement]
标记Hits
数组,你可以消除你的 Hits
类,如下所示:
[XmlRoot("SearchResponse")]
public sealed class SearchResponse
{
[XmlElement("Response", Type = typeof(Response))]
public Response[] Responses { get; set; }
[XmlElement("HitsCount", Type = typeof(HitsCount))]
public HitsCount[] HitsCount { get; set; }
[XmlArray("Hits")] // Indicates that the hits will be serialized with an outer container element named "Hits".
[XmlArrayItem("Hit")] // Indicates that each inner entry element will be named "Hit".
public Hit [] Hits { get; set; }
}
更新
这
public string this[XName name] { get; set; }
是一个索引器。 请参阅使用索引器(C# 编程指南)。 我添加了它,以便很容易执行以下操作:
var description = hit["Description"];
var title = hit["Title"];
索引器查找具有指定名称的第一个 XML 元素,并返回其文本值。 如果你不想要它,你可以把它排除在外——这只是为了方便。