如何在 c# 中使用名称相同但属性和结构不同的元素反序列化 XML



我有一个具有以下结构的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>

我需要以最快的方式将每个块反序列化为单独的对象。 到目前为止,我想出了使用 LINQ 手动搜索每个块,并分别反序列化每个块,如下所示:

var Xblock1 = root.Elements("Block").FirstOrDefault(e => e.Attribute("id")?.Value == "1");
Block1 block1 = (Block1)(serializer.Deserialize(Xblock1.CreateReader()));

但我相信有更优化的方法可以做到这一点。

感谢您的时间

XML 序列化速度很慢,需要类和属性名称。相反,我推荐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:temptest.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我在此答案末尾链接了该类。

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();
}

输出:

1
2
3
Method 1: 0,0759927
1
2
3
Method 2: 0,0030262

下面的codde是由XSD.EXE /c file.xsd生成的,所以你应该从你的XML创建一个XSD(Visual Studio可以为你做(:

//------------------------------------------------------------------------------
// <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;
}
}
}

最新更新