C#复杂XML反序列化为实体对象两种方式 (上)

简介: C#复杂XML反序列化为实体对象两种方式

前言

  今天主要讲的是如何把通过接口获取到的Xml数据转换成(反序列化)我们想要的实体对象,当然Xml反序列化和Json反序列化的方式基本上都是大同小异。都是我们事先定义好对应的对应的Xml实体模型,不过Xml是通过XmlSerializer类的相关特性来对实体对象和 XML文档之间进行序列化和反序列化操作的。序列化和反序列化其实都还好,我们可以调用封装好的XmlHelper帮助类即可实现,最关键的是我们该如何去定义这些实体模型(Model)。当你遇到对方接口一下子返回一大串的Xml数据并且里面存在很多不同的Xml节点,你该怎么办一个一个去解析这些节点到模型上去吗?本文我主要讲两种方式,第一种方法是通过手写的方式去定义Xml的实体对象模型类,第二种方法是通过Visual Studio自带的生成Xml实体对象模型类。

需要操作的Xml数据

注意:以下是我稍微简化的Xml数据,实际数据可能比这里要复杂个大几倍。

<?xml version="1.0" encoding="utf-8" ?>
<envelope>
    <header>
        <version port="1111" host="www.baidu.com">successfuly</version>
        <timestamp>20211216081218</timestamp>
    </header>
    <response type="cities" product="hotel">
        <cities>
            <city>
                <code value="zg" />
                <city_tax value="true" />
                <names>
                    <name language="fr" value="ABANO TERME - PADOUE" />
                    <name language="en" value="ABANO TERME - PADUE" />
                    <name language="nl" value="ABANO TERME - PADUE" />
                </names>
            </city>
            <city>
                <code value="hk" />
                <city_tax value="false" />
                <names>
                    <name language="fr" value="ABBADIA SAN SALVATORE - SIENNE" />
                    <name language="en" value="ABBADIA SAN SALVATORE - SIENA" />
                    <name language="nl" value="ABBADIA SAN SALVATORE - SIENA" />
                </names>
            </city>
        </cities>
    </response>
</envelope>

一、通过是手写的方式去定义Xml的实体对象模型类

当然假如你有耐心、时间充足并且眼睛好的话可以使用这种手写的方式去定义,很多情况写到最好都会把自己给写糊涂了(可能是我年纪大了的原因)。

namespace Practices.Models
{
    /// <summary>
    /// Envelope
    /// </summary>
    [XmlType(TypeName = "envelope")]
    public class CityDataModel
    {
        /// <summary>
        /// header
        /// </summary>
        [XmlElement("header")]
        public Header header { get; set; }
        /// <summary>
        /// response
        /// </summary>
        [XmlElement("response")]
        public Response response { get; set; }
    }
    /// <summary>
    /// Header
    /// </summary>
    [XmlType(TypeName = "header")]
    public class Header
    {
        /// <summary>
        /// version
        /// </summary>
        [XmlElement("version")]
        public Version version { get; set; }
        /// <summary>
        /// timestamp
        /// </summary>
        [XmlElement("timestamp")]
        public string timestamp { get; set; }
    }
    /// <summary>
    /// Version
    /// </summary>
    public class Version
    {
        /// <summary>
        /// port
        /// </summary>
        [XmlAttribute("port")]
        public string port { get; set; }
        /// <summary>
        /// host
        /// </summary>
        [XmlAttribute("host")]
        public string host { get; set; }
        /// <summary>
        /// value:XmlTextAttribute指示该属性作为XML文本处理
        /// </summary>
        [XmlTextAttribute()]
        public string value { get; set; }
    }
    /// <summary>
    /// Response
    /// </summary>
    [XmlType(TypeName = "response")]
    public class Response
    {
        /// <summary>
        /// type
        /// </summary>
        [XmlAttribute]
        public string type { get; set; }
        /// <summary>
        /// product
        /// </summary>
        [XmlAttribute]
        public string product { get; set; }
        /// <summary>
        /// cities
        /// </summary>
        [XmlArray("cities")]
        public List<City> cities { get; set; }
    }
    /// <summary>
    /// class: City
    /// </summary>
    [XmlType(TypeName = "city")]
    public class City
    {
        /// <summary>
        /// code
        /// </summary>
        [XmlElement("code")]
        public Code code { get; set; }
        /// <summary>
        /// city_tax
        /// </summary>
        [XmlElement("city_tax")]
        public City_tax city_tax { get; set; }
        /// <summary>
        /// names
        /// </summary>
        [XmlArray("names")]
        public List<Name> names { get; set; }
    }
    /// <summary>
    /// class: Code
    /// </summary>
    [XmlType(TypeName = "code")]
    public class Code
    {
        /// <summary>
        /// 
        /// </summary>
        [XmlAttribute("value")]
        public string value { get; set; }
    }
    /// <summary>
    /// class: City_tax
    /// </summary>
    [XmlType(TypeName = "city_tax")]
    public class City_tax
    {
        /// <summary>
        /// 
        /// </summary>
        [XmlAttribute("value")]
        public string value { get; set; }
    }
    /// <summary>
    /// class: Name
    /// </summary>
    [XmlType(TypeName = "name")]
    public class Name
    {
        /// <summary>
        /// 
        /// </summary>
        [XmlAttribute("language")]
        public string language { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [XmlAttribute("value")]
        public string value { get; set; }
    }
}

二、通过Visual Studio自带的生成Xml实体对象模型类

Vs被称为宇宙最强IDE也不是没有理由的,它集成了很多自动创建功能,如自动生成Json类、Xml类等,虽然说使用Vs自动生成的Xml模型可读性有点差并且有些冗余,但是快捷省事,只需要略微改动一下即可使用。

1、首先Ctrl+C复制你需要生成的Xml文档内容

2、找到编辑=》选择性粘贴=》将Xml粘贴为类

1336199-20220327001703880-950316713.png

3、以下是使用VS自动生成的Xml类

namespace Practices.Models
{
    // 注意: 生成的代码可能至少需要 .NET Framework 4.5 或 .NET Core/Standard 2.0。
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    //TODO:注意这里因为我把类名改成了我自定义的,所以在TypeName这里需要声明Xml文档的节点名
    [System.Xml.Serialization.XmlTypeAttribute(typeName: "envelope")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class NewCityDataModel
    {
        private envelopeHeader headerField;
        private envelopeResponse responseField;
        /// <remarks/>
        public envelopeHeader header
        {
            get
            {
                return this.headerField;
            }
            set
            {
                this.headerField = value;
            }
        }
        /// <remarks/>
        public envelopeResponse response
        {
            get
            {
                return this.responseField;
            }
            set
            {
                this.responseField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeHeader
    {
        private envelopeHeaderVersion versionField;
        private ulong timestampField;
        /// <remarks/>
        public envelopeHeaderVersion version
        {
            get
            {
                return this.versionField;
            }
            set
            {
                this.versionField = value;
            }
        }
        /// <remarks/>
        public ulong timestamp
        {
            get
            {
                return this.timestampField;
            }
            set
            {
                this.timestampField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeHeaderVersion
    {
        private ushort portField;
        private string hostField;
        private string valueField;
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public ushort port
        {
            get
            {
                return this.portField;
            }
            set
            {
                this.portField = value;
            }
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string host
        {
            get
            {
                return this.hostField;
            }
            set
            {
                this.hostField = value;
            }
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlTextAttribute()]
        public string Value
        {
            get
            {
                return this.valueField;
            }
            set
            {
                this.valueField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeResponse
    {
        private envelopeResponseCity[] citiesField;
        private string typeField;
        private string productField;
        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("city", IsNullable = false)]
        public envelopeResponseCity[] cities
        {
            get
            {
                return this.citiesField;
            }
            set
            {
                this.citiesField = value;
            }
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string type
        {
            get
            {
                return this.typeField;
            }
            set
            {
                this.typeField = value;
            }
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string product
        {
            get
            {
                return this.productField;
            }
            set
            {
                this.productField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeResponseCity
    {
        private envelopeResponseCityCode codeField;
        private envelopeResponseCityCity_tax city_taxField;
        private envelopeResponseCityName[] namesField;
        /// <remarks/>
        public envelopeResponseCityCode code
        {
            get
            {
                return this.codeField;
            }
            set
            {
                this.codeField = value;
            }
        }
        /// <remarks/>
        public envelopeResponseCityCity_tax city_tax
        {
            get
            {
                return this.city_taxField;
            }
            set
            {
                this.city_taxField = value;
            }
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("name", IsNullable = false)]
        public envelopeResponseCityName[] names
        {
            get
            {
                return this.namesField;
            }
            set
            {
                this.namesField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeResponseCityCode
    {
        private string valueField;
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string value
        {
            get
            {
                return this.valueField;
            }
            set
            {
                this.valueField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeResponseCityCity_tax
    {
        private bool valueField;
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public bool value
        {
            get
            {
                return this.valueField;
            }
            set
            {
                this.valueField = value;
            }
        }
    }
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class envelopeResponseCityName
    {
        private string languageField;
        private string valueField;
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string language
        {
            get
            {
                return this.languageField;
            }
            set
            {
                this.languageField = value;
            }
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string value
        {
            get
            {
                return this.valueField;
            }
            set
            {
                this.valueField = value;
            }
        }
    }
}

验证两个Xml类是否能够反序列化成功

 /// <summary>     
        /// 读取Xml文件内容反序列化为指定的对象  
        /// </summary>    
        /// <param name="filePath">Xml文件的位置(绝对路径)</param>  
        /// <returns></returns>    
        public static T DeserializeFromXml<T>(string filePath)
        {
            try
            {
                if (!File.Exists(filePath))
                    throw new ArgumentNullException(filePath + " not Exists");
                using (StreamReader reader = new StreamReader(filePath))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(T));
                    T ret = (T)xs.Deserialize(reader);
                    return ret;
                }
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }


相关文章
|
2月前
|
XML JSON 数据处理
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
178 61
C# 中的 XML 与 JSON 数据处理
|
1月前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
116 65
|
7天前
|
JSON 程序员 C#
使用 C# 比较两个对象是否相等的7个方法总结
比较对象是编程中的一项基本技能,在实际业务中经常碰到,比如在ERP系统中,企业的信息非常重要,每一次更新,都需要比较记录更新前后企业的信息,直接比较通常只能告诉我们它们是否指向同一个内存地址,那我们应该怎么办呢?分享 7 个方法给你!
|
1月前
|
XML 存储 缓存
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
89 0
|
1月前
|
XML JSON 前端开发
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
358 0
|
1月前
|
XML 安全 网络协议
Xxe外部实体注入(XML External Entity Injection)
Xxe外部实体注入(XML External Entity Injection)
|
2月前
|
C# 数据安全/隐私保护
C# 一分钟浅谈:类与对象的概念理解
【9月更文挑战第2天】本文从零开始详细介绍了C#中的类与对象概念。类作为一种自定义数据类型,定义了对象的属性和方法;对象则是类的实例,拥有独立的状态。通过具体代码示例,如定义 `Person` 类及其实例化过程,帮助读者更好地理解和应用这两个核心概念。此外,还总结了常见的问题及解决方法,为编写高质量的面向对象程序奠定基础。
25 2
|
6月前
|
C#
C#的类和对象的概念学习案例刨析
【5月更文挑战第17天】C#是一种面向对象的语言,以类和对象为核心。类作为对象的模板,定义了属性(如Name, Age)和行为(如Greet)。对象是类的实例,可设置属性值。封装通过访问修饰符隐藏实现细节,如Customer类的私有name字段通过Name属性访问。继承允许新类(如Employee)从现有类(Person)继承并扩展。多态让不同对象(如Circle, Square)共享相同接口(Shape),实现抽象方法Area,提供灵活的代码设计。
65 1
|
6月前
|
XML 存储 C#
C# xml文档反序列化记事
本文介绍了使用XmlSerializer进行XML序列化和反序列化的关键点。包括:1) 以独占方式读取XML文件以避免并发问题;2) 当元素名与类型名不一致时,可通过`[XmlArrayItem]`指定元素名,或创建继承自原始类型的子类;3) 处理DateTime反序列化错误,通过中间字符串属性转换;4) 提到了常用C#特性如`[XmlRoot]`, `[XmlElement]`, `[XmlAttribute]`, `[XmlIgnore]`和`[XmlArrayItem]`的作用。
|
1月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
57 1