繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM