C# 如何在c语言中使用名称相同但属性和结构不同的元素反序列化XML#
我有一个具有以下结构的XML响应:C# 如何在c语言中使用名称相同但属性和结构不同的元素反序列化XML#,c#,xml,deserialization,xml-deserialization,C#,Xml,Deserialization,Xml Deserialization,我有一个具有以下结构的XML响应: <Response> <Block id="1"> <Some_Data_1><Some_Data_1> <Some_Data_2><Some_Data_2> </Block> <Block id="2"> <Another_Data_3><
<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>
但我相信有更优化的方法来做到这一点
非常感谢您的时间Xml序列化速度慢,需要类和属性名。相反,我推荐XMLLINQ,它速度更快,不需要预定义的属性名
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());
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用System.Xml.Linq;
命名空间控制台应用程序1
{
班级计划
{
常量字符串文件名=@“c:\temp\test.xml”;
静态void Main(字符串[]参数)
{
XDocument doc=XDocument.Load(文件名);
Dictionary dict=文档子体(“块”)
.GroupBy(x=>(int)x.Attribute(“id”),y=>y.Elements()
.GroupBy(a=>a.Name.LocalName,b=>(字符串)b)
.ToDictionary(a=>a.Key,b=>b.FirstOrDefault())
.ToDictionary(x=>x.Key,y=>y.FirstOrDefault());
}
}
}
Xml序列化速度慢,需要类和属性名。相反,我推荐XMLLINQ,它速度更快,不需要预定义的属性名
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());
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用System.Xml.Linq;
命名空间控制台应用程序1
{
班级计划
{
常量字符串文件名=@“c:\temp\test.xml”;
静态void Main(字符串[]参数)
{
XDocument doc=XDocument.Load(文件名);
Dictionary dict=文档子体(“块”)
.GroupBy(x=>(int)x.Attribute(“id”),y=>y.Elements()
.GroupBy(a=>a.Name.LocalName,b=>(字符串)b)
.ToDictionary(a=>a.Key,b=>b.FirstOrDefault())
.ToDictionary(x=>x.Key,y=>y.FirstOrDefault());
}
}
}
第一个方法是Serialize,第二个方法是@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();
}
下面的codde是由XSD.EXE/c file.XSD
生成的,因此您应该从XML中创建一个XSD(Visual Studio可以为您这样做):
//------------------------------------------------------------------------------
//
//这段代码是由一个工具生成的。
//运行时版本:4.0.30319.42000
//
//对此文件的更改可能会导致不正确的行为,如果
//重新生成代码。
//
//------------------------------------------------------------------------------
使用System.Xml.Serialization;
//
//此源代码由xsd自动生成,版本=4.8.3928.0。
//
///
[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”,“4.8.3928.0”)]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute(“代码”)]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace=”“,IsNullable=false)]
公众部分班级反应{
私有响应块[]块域;
///
[System.Xml.Serialization.XmlElementAttribute(“块”)]
公共响应块[]块{
得到{
返回此.blockField;
}
设置{
this.blockField=值;
}
}
}
///
[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”,“4.8.3928.0”)]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute(“代码”)]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
公共部分类响应块{
私有字符串另一个_数据_3字段;
私有字符串另一个_数据_4字段;
私有字符串另一个_数据_5字段;
私有字符串部分数据字段;
私有字符串某些_数据_2字段;
私有字符串[]文本字段;
专用字节字段;
///
公共字符串另一个\u数据\u 3{
得到{
返回此。另一个_数据_3字段;
}
设置{
this.other_Data_3Field=值;
}
}
///
公共字符串另一个\u数据\u 4{
得到{
返回this.other_Data_4字段;
}
设置{
this.other_Data_4Field=值;
}
}
///
公共字符串另一个_数据_5{
得到{
返回this.other_Data_5字段;
}
设置{
this.other_Data_5Field=值;
}
}
///
公共字符串某些\u数据\u 1{
得到{
返回this.some_Data_1字段;
}
设置{
this.some_Data_1字段=值;
}
}
///
公共字符串某些\u数据\u 2{
得到{
返回this.some_Data_2字段;
}
设置{
this.some_Data_2字段=值;
}
}
///
[System.Xml.Serialization.XmlTextAttribute()]
公共字符串[]文本{
得到{
返回this.textField;
}
设置{
this.textField=值;
}
}
///
[System.Xml.Serialization.XmlAttributeAttribute()]
公共字节id{
得到{
返回此.idField;
}
设置{
this.idField=值;
}
}
}
第一个方法是Serialize,第二个方法是@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();
}
下面的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;
}
}
}