前言
今天主要讲的是如何把通过接口获取到的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">successfulyversion> <timestamp>20211216081218timestamp> 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 { ////// Envelope /// [XmlType(TypeName = "envelope")] public class CityDataModel { /// /// header /// [XmlElement("header")] public Header header { get; set; } /// /// response /// [XmlElement("response")] public Response response { get; set; } } /// /// Header /// [XmlType(TypeName = "header")] public class Header { /// /// version /// [XmlElement("version")] public Version version { get; set; } /// /// timestamp /// [XmlElement("timestamp")] public string timestamp { get; set; } } /// /// Version /// public class Version { /// /// port /// [XmlAttribute("port")] public string port { get; set; } /// /// host /// [XmlAttribute("host")] public string host { get; set; } /// /// value:XmlTextAttribute指示该属性作为XML文本处理 /// [XmlTextAttribute()] public string value { get; set; } } /// /// Response /// [XmlType(TypeName = "response")] public class Response { /// /// type /// [XmlAttribute] public string type { get; set; } /// /// product /// [XmlAttribute] public string product { get; set; } /// /// cities /// [XmlArray("cities")] public List cities { get; set; } } /// /// class: City /// [XmlType(TypeName = "city")] public class City { /// /// code /// [XmlElement("code")] public Code code { get; set; } /// /// city_tax /// [XmlElement("city_tax")] public City_tax city_tax { get; set; } /// /// names /// [XmlArray("names")] public List names { get; set; } } /// /// class: Code /// [XmlType(TypeName = "code")] public class Code { /// /// /// [XmlAttribute("value")] public string value { get; set; } } /// /// class: City_tax /// [XmlType(TypeName = "city_tax")] public class City_tax { /// /// /// [XmlAttribute("value")] public string value { get; set; } } /// /// class: Name /// [XmlType(TypeName = "name")] public class Name { /// /// /// [XmlAttribute("language")] public string language { get; set; } /// /// /// [XmlAttribute("value")] public string value { get; set; } } }
二、通过Visual Studio自带的生成Xml实体对象模型类
Vs被称为宇宙最强IDE也不是没有理由的,它集成了很多自动创建功能,如自动生成Json类、Xml类等,虽然说使用Vs自动生成的Xml模型可读性有点差并且有些冗余,但是快捷省事,只需要略微改动一下即可使用。
1、首先Ctrl+C复制你需要生成的Xml文档内容
2、找到编辑=》选择性粘贴=》将Xml粘贴为类
3、以下是使用VS自动生成的Xml类
namespace Practices.Models { // 注意: 生成的代码可能至少需要 .NET Framework 4.5 或 .NET Core/Standard 2.0。 ///[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; /// public envelopeHeader header { get { return this.headerField; } set { this.headerField = value; } } /// public envelopeResponse response { get { return this.responseField; } set { this.responseField = value; } } } /// [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeHeader { private envelopeHeaderVersion versionField; private ulong timestampField; /// public envelopeHeaderVersion version { get { return this.versionField; } set { this.versionField = value; } } /// public ulong timestamp { get { return this.timestampField; } set { this.timestampField = value; } } } /// [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; /// [System.Xml.Serialization.XmlAttributeAttribute()] public ushort port { get { return this.portField; } set { this.portField = value; } } /// [System.Xml.Serialization.XmlAttributeAttribute()] public string host { get { return this.hostField; } set { this.hostField = value; } } /// [System.Xml.Serialization.XmlTextAttribute()] public string Value { get { return this.valueField; } set { this.valueField = value; } } } /// [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; /// [System.Xml.Serialization.XmlArrayItemAttribute("city", IsNullable = false)] public envelopeResponseCity[] cities { get { return this.citiesField; } set { this.citiesField = value; } } /// [System.Xml.Serialization.XmlAttributeAttribute()] public string type { get { return this.typeField; } set { this.typeField = value; } } /// [System.Xml.Serialization.XmlAttributeAttribute()] public string product { get { return this.productField; } set { this.productField = value; } } } /// [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; /// public envelopeResponseCityCode code { get { return this.codeField; } set { this.codeField = value; } } /// public envelopeResponseCityCity_tax city_tax { get { return this.city_taxField; } set { this.city_taxField = value; } } /// [System.Xml.Serialization.XmlArrayItemAttribute("name", IsNullable = false)] public envelopeResponseCityName[] names { get { return this.namesField; } set { this.namesField = value; } } } /// [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCityCode { private string valueField; /// [System.Xml.Serialization.XmlAttributeAttribute()] public string value { get { return this.valueField; } set { this.valueField = value; } } } /// [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCityCity_tax { private bool valueField; /// [System.Xml.Serialization.XmlAttributeAttribute()] public bool value { get { return this.valueField; } set { this.valueField = value; } } } /// [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCityName { private string languageField; private string valueField; /// [System.Xml.Serialization.XmlAttributeAttribute()] public string language { get { return this.languageField; } set { this.languageField = value; } } /// [System.Xml.Serialization.XmlAttributeAttribute()] public string value { get { return this.valueField; } set { this.valueField = value; } } } }
验证两个Xml类是否能够反序列化成功
////// 读取Xml文件内容反序列化为指定的对象 /// /// Xml文件的位置(绝对路径) /// public static T DeserializeFromXml (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文件内容增删改查清)
https://www.cnblogs.com/Can-daydayup/p/16036872.html
C#XmlHelper帮助类操作Xml文档的通用方法汇总
https://www.cnblogs.com/Can-daydayup/p/16058817.html
.NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结
https://www.cnblogs.com/Can-daydayup/p/16052873.html