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

picture.image

picture.image

前言

  今天主要讲的是如何把通过接口获取到的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粘贴为类

picture.image

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

C# XML基础入门(XML文件内容增删改查清)

C# XML基础入门(XML文件内容增删改查清)

C#XmlHelper帮助类操作Xml文档的通用方法汇总

C#XmlHelper帮助类操作Xml文档的通用方法汇总

.NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结

.NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结

picture.image


学习是一个永无止境的过程,你知道的越多,你不知道的也会越多,在有限的时间内坚持每天多学一点,你一定能成为你想要成为的那个人。不积跬步无以至千里,不积小流无以成江河!!!

picture.image

See you next good day~

picture.image

0
0
0
0
评论
未登录
暂无评论