![](/img/trans.png)
[英]Deserialize different xml elements with same name into different C# classes
[英]How to deserialize XML with elements with same name, but different attributes and structure in c#
我有一个 XML 响应,其结构如下:
<Response>
<Block id="1">
<Some_Data_1><Some_Data_1>
<Some_Data_2><Some_Data_2>
</Block>
<Block id="2">
<Another_Data_3><Another_Data_3>
<Another_Data_4><Another_Data_4>
<Another_Data_5><Another_Data_5>
</Block>
<Block id="3">
...
</Block>
</Response>
我需要以最快的方式将每个块反序列化为单独的 object。 到目前为止,我想出了使用 LINQ 手动搜索每个块,并分别反序列化每个块,如下所示:
var Xblock1 = root.Elements("Block").FirstOrDefault(e => e.Attribute("id")?.Value == "1");
Block1 block1 = (Block1)(serializer.Deserialize(Xblock1.CreateReader()));
但我相信有更优化的方法来做到这一点。
珍惜你的时间
Xml 序列化速度很慢,需要 class 和属性名称。 相反,我推荐 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);
Dictionary<int, Dictionary<string, string>> dict = doc.Descendants("Block")
.GroupBy(x => (int)x.Attribute("id"), y => y.Elements()
.GroupBy(a => a.Name.LocalName, b => (string)b)
.ToDictionary(a => a.Key, b => b.FirstOrDefault()))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
第一种方法是使用序列化,第二种是来自@jdweng 的答案的副本。
如前所述,使用Serialize
的方法要慢得多!
对于第一种方法,您还需要一个由 XSD.EXE 生成的 class ,我在这个答案的末尾链接了它。
static void Main(string[] args)
{
DateTime start;
start = DateTime.Now;
XmlSerializer ser2 = new XmlSerializer(typeof(Response));
FileStream f = new FileStream(FILENAME, FileMode.Open);
Response response = ser2.Deserialize(f) as Response;
foreach (var item in response.Block)
{
Console.WriteLine(item.id);
}
f.Close();
Console.WriteLine("Method 1: {0}", ((DateTime.Now - start).TotalMilliseconds / 1000));
start = DateTime.Now;
XDocument doc = XDocument.Load(FILENAME);
Dictionary<int, Dictionary<string, string>> dict = doc.Descendants("Block")
.GroupBy(x => (int)x.Attribute("id"), y => y.Elements()
.GroupBy(a => a.Name.LocalName, b => (string)b)
.ToDictionary(a => a.Key, b => b.FirstOrDefault()))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
foreach (var item in dict.Keys)
{
Console.WriteLine(item);
}
Console.WriteLine("Method 2: {0}", ((DateTime.Now - start).TotalMilliseconds / 1000));
Console.ReadLine();
}
output:
1
2
3
Method 1: 0,0759927
1
2
3
Method 2: 0,0030262
Below codde is generated by XSD.EXE /c file.xsd
, so from your XML you should create an XSD (which Visual Studio can do for you):
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.8.3928.0.
//
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class Response {
private ResponseBlock[] blockField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Block")]
public ResponseBlock[] Block {
get {
return this.blockField;
}
set {
this.blockField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class ResponseBlock {
private string another_Data_3Field;
private string another_Data_4Field;
private string another_Data_5Field;
private string some_Data_1Field;
private string some_Data_2Field;
private string[] textField;
private byte idField;
/// <remarks/>
public string Another_Data_3 {
get {
return this.another_Data_3Field;
}
set {
this.another_Data_3Field = value;
}
}
/// <remarks/>
public string Another_Data_4 {
get {
return this.another_Data_4Field;
}
set {
this.another_Data_4Field = value;
}
}
/// <remarks/>
public string Another_Data_5 {
get {
return this.another_Data_5Field;
}
set {
this.another_Data_5Field = value;
}
}
/// <remarks/>
public string Some_Data_1 {
get {
return this.some_Data_1Field;
}
set {
this.some_Data_1Field = value;
}
}
/// <remarks/>
public string Some_Data_2 {
get {
return this.some_Data_2Field;
}
set {
this.some_Data_2Field = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte id {
get {
return this.idField;
}
set {
this.idField = value;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.