【问题标题】:How to deserialize XML with elements with same name, but different attributes and structure in c#如何在c#中使用具有相同名称但不同属性和结构的元素反序列化XML
【发布时间】:2020-10-25 13:31:31
【问题描述】:

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

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

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

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

珍惜你的时间

【问题讨论】:

    标签: c# xml deserialization xml-deserialization


    【解决方案1】:

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

    【讨论】:

    • 谢谢,但是如果我最终需要它作为对象呢?而且我知道所有的属性名称,这不是问题
    • 你要求快。创建具有对象名称(或匿名)的类并使用比序列化更快的 xml linx。
    【解决方案2】:

    第一种方法是使用序列化,第二种方法是从@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
    

    下面的代码是由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;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2015-10-08
      • 2020-01-14
      相关资源
      最近更新 更多