[C#]记一次解析XML转对象的笔记
项目中调用第三方API,返回格式是XML字符串,需要将XML反序列化为对象,格式如下:
1 <?xml version="1.0"?> 2 <Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" totalCount="123" resultCode="ABC" resultMessage="测试"> 3 <profile lastName="李" firstName="爽" dateOfBirth="XX0816" age="" gender="1" address="浙江省 杭州富阳市 东州工业园区3号路1号杭州龙盛工贸有限公" email="htlslll@163.com" cellEmail="" socialMedia="" homePhone="" cellPhone="18857199925" contactabiltyMail="1" contactabiltyEmail="1" contactabiltyCellEmail="0" contactabiltyHomePhone="1" contactabiltyCellPhone="1" contactabiltyText="1" contactabiltySocialMedia="0" vipLevel="2" memberId="OC540C00016824" saAccount="660996" classa="小姐" homeStoreCode="OC54" /> 4 <purchaseHistory> 5 <departmentPurchase totalLifeTimeSale="36791" totalTYAmount="21705" lastTxn="20160829" totalTYUnitCnt="9" firstTxn="20160713"> 6 <department categoryName="D08" tyAmount="2970" tyUnitCnt="2" /> 7 <department categoryName="D01" tyAmount="9750" tyUnitCnt="3" /> 8 <department categoryName="D02" tyAmount="8985" tyUnitCnt="4" /> 9 </departmentPurchase> 10 <ratePurchase totalLyAmount="0" totalLyRate="0" totalTyAmount="21705" totalTyRate="100" totalLifeTimeAmount="36791" totalLifeTimeRate="100"> 11 <rate categoryName="Retail" lyAmount="" lyRate="0" lyToDate="0" tyAmount="21705" tyRate="100" tyToDate="21705" lifeTimeAmount="36791" lifeTimeRate="100" lyTyChange="100" /> 12 </ratePurchase> 13 <storeRatePurchase> 14 <storeRate /> 15 </storeRatePurchase> 16 </purchaseHistory> 17 <vipStatus issueDate="20140629" issueShop="OC54" ptsToUpgrade="21705" expiryDate="20170731" upgradeShop="" ptsToRenew="8130" /> 18 <comments comment="第一场雪" /> 19 </Response>
按照这个格式我需要定义相应的对象来接收,定义如下:
1 /// <summary> 2 /// 3 /// </summary> 4 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 5 [System.SerializableAttribute()] 6 [System.ComponentModel.DesignerCategoryAttribute("code")] 7 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "Response")] 8 public class Response 9 { 10 [System.Xml.Serialization.XmlAttributeAttribute()] 11 public string totalCount { get; set; } 12 13 [System.Xml.Serialization.XmlAttributeAttribute()] 14 public string resultCode { get; set; } 15 16 [System.Xml.Serialization.XmlAttributeAttribute()] 17 public string resultMessage { get; set; } 18 19 [System.Xml.Serialization.XmlElementAttribute("profile", typeof(profile))] 20 public profile profile { get; set; } 21 22 [System.Xml.Serialization.XmlElementAttribute("purchaseHistory", typeof(purchaseHistory))] 23 public purchaseHistory purchaseHistory { get; set; } 24 25 [System.Xml.Serialization.XmlElementAttribute("vipStatus", typeof(vipStatus))] 26 public vipStatus vipStatus { get; set; } 27 28 [System.Xml.Serialization.XmlElementAttribute("comments", typeof(comments))] 29 public comments comments { get; set; } 30 } 31 32 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 33 [System.SerializableAttribute()] 34 [System.ComponentModel.DesignerCategoryAttribute("code")] 35 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 36 public class profile 37 { 38 [System.Xml.Serialization.XmlAttributeAttribute()] 39 public string lastName { get; set; } 40 41 [System.Xml.Serialization.XmlAttributeAttribute()] 42 public string firstName { get; set; } 43 44 [System.Xml.Serialization.XmlAttributeAttribute()] 45 public string dateOfBirth { get; set; } 46 47 [System.Xml.Serialization.XmlAttributeAttribute()] 48 public string age { get; set; } 49 50 [System.Xml.Serialization.XmlAttributeAttribute()] 51 public string gender { get; set; } 52 53 [System.Xml.Serialization.XmlAttributeAttribute()] 54 public string address { get; set; } 55 56 [System.Xml.Serialization.XmlAttributeAttribute()] 57 public string email { get; set; } 58 59 [System.Xml.Serialization.XmlAttributeAttribute()] 60 public string cellEmail { get; set; } 61 62 [System.Xml.Serialization.XmlAttributeAttribute()] 63 public string socialMedia { get; set; } 64 65 [System.Xml.Serialization.XmlAttributeAttribute()] 66 public string homePhone { get; set; } 67 68 [System.Xml.Serialization.XmlAttributeAttribute()] 69 public string cellPhone { get; set; } 70 71 [System.Xml.Serialization.XmlAttributeAttribute()] 72 public string contactabiltyMail { get; set; } 73 74 [System.Xml.Serialization.XmlAttributeAttribute()] 75 public string contactabiltyEmail { get; set; } 76 77 [System.Xml.Serialization.XmlAttributeAttribute()] 78 public string contactabiltyCellEmail { get; set; } 79 80 [System.Xml.Serialization.XmlAttributeAttribute()] 81 public string contactabiltyHomePhone { get; set; } 82 83 [System.Xml.Serialization.XmlAttributeAttribute()] 84 public string contactabiltyCellPhone { get; set; } 85 86 [System.Xml.Serialization.XmlAttributeAttribute()] 87 public string contactabiltyText { get; set; } 88 89 [System.Xml.Serialization.XmlAttributeAttribute()] 90 public string contactabiltySocialMedia { get; set; } 91 92 [System.Xml.Serialization.XmlAttributeAttribute()] 93 public string vipLevel { get; set; } 94 95 [System.Xml.Serialization.XmlAttributeAttribute()] 96 public string memberId { get; set; } 97 98 [System.Xml.Serialization.XmlAttributeAttribute()] 99 public string saAccount { get; set; } 100 101 [System.Xml.Serialization.XmlAttributeAttribute()] 102 public string classa { get; set; } 103 104 [System.Xml.Serialization.XmlAttributeAttribute()] 105 public string homeStoreCode { get; set; } 106 } 107 108 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 109 [System.SerializableAttribute()] 110 [System.ComponentModel.DesignerCategoryAttribute("code")] 111 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 112 public class purchaseHistory 113 { 114 115 [System.Xml.Serialization.XmlElementAttribute("departmentPurchase", typeof(departmentPurchase))] 116 public departmentPurchase departmentPurchase { get; set; } 117 118 [System.Xml.Serialization.XmlElementAttribute("ratePurchase", typeof(ratePurchase))] 119 public ratePurchase ratePurchase { get; set; } 120 121 [System.Xml.Serialization.XmlElementAttribute("storeRatePurchase", typeof(storeRatePurchase))] 122 public storeRatePurchase storeRatePurchase { get; set; } 123 } 124 125 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 126 [System.SerializableAttribute()] 127 [System.ComponentModel.DesignerCategoryAttribute("code")] 128 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 129 public class departmentPurchase 130 { 131 [System.Xml.Serialization.XmlAttributeAttribute()] 132 public string totalTYAmount { get; set; } 133 134 [System.Xml.Serialization.XmlAttributeAttribute()] 135 public string totalTYUnitCnt { get; set; } 136 137 [System.Xml.Serialization.XmlAttributeAttribute()] 138 public string firstTxn { get; set; } 139 140 [System.Xml.Serialization.XmlAttributeAttribute()] 141 public string lastTxn { get; set; } 142 143 [System.Xml.Serialization.XmlAttributeAttribute()] 144 public string totalLifeTimeSale { get; set; } 145 146 [System.Xml.Serialization.XmlElementAttribute("department", typeof(List<department>), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)] 147 public List<department> department { get; set; } 148 } 149 150 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 151 [System.SerializableAttribute()] 152 [System.ComponentModel.DesignerCategoryAttribute("code")] 153 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 154 public class department 155 { 156 [System.Xml.Serialization.XmlAttributeAttribute()] 157 public string categoryName { get; set; } 158 159 [System.Xml.Serialization.XmlAttributeAttribute()] 160 public string tyAmount { get; set; } 161 162 [System.Xml.Serialization.XmlAttributeAttribute()] 163 public string tyUnitCnt { get; set; } 164 } 165 166 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 167 [System.SerializableAttribute()] 168 [System.ComponentModel.DesignerCategoryAttribute("code")] 169 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 170 public class ratePurchase 171 { 172 [System.Xml.Serialization.XmlAttributeAttribute()] 173 public string totalLyAmount { get; set; } 174 175 [System.Xml.Serialization.XmlAttributeAttribute()] 176 public string totalLyRate { get; set; } 177 178 [System.Xml.Serialization.XmlAttributeAttribute()] 179 public string totalTyAmount { get; set; } 180 181 [System.Xml.Serialization.XmlAttributeAttribute()] 182 public string totalTyRate { get; set; } 183 184 [System.Xml.Serialization.XmlAttributeAttribute()] 185 public string totalLifeTimeAmount { get; set; } 186 187 [System.Xml.Serialization.XmlAttributeAttribute()] 188 public string totalLifeTimeRate { get; set; } 189 190 [System.Xml.Serialization.XmlElementAttribute("rate", typeof(rate))] 191 public rate rate { get; set; } 192 } 193 194 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 195 [System.SerializableAttribute()] 196 [System.ComponentModel.DesignerCategoryAttribute("code")] 197 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 198 public class rate 199 { 200 [System.Xml.Serialization.XmlAttributeAttribute()] 201 public string categoryName { get; set; } 202 203 [System.Xml.Serialization.XmlAttributeAttribute()] 204 public string lyAmount { get; set; } 205 206 [System.Xml.Serialization.XmlAttributeAttribute()] 207 public string lyRate { get; set; } 208 209 [System.Xml.Serialization.XmlAttributeAttribute()] 210 public string lyToDate { get; set; } 211 212 [System.Xml.Serialization.XmlAttributeAttribute()] 213 public string tyAmount { get; set; } 214 215 [System.Xml.Serialization.XmlAttributeAttribute()] 216 public string tyRate { get; set; } 217 [System.Xml.Serialization.XmlAttributeAttribute()] 218 219 public string tyToDate { get; set; } 220 221 [System.Xml.Serialization.XmlAttributeAttribute()] 222 public string lifeTimeAmount { get; set; } 223 224 [System.Xml.Serialization.XmlAttributeAttribute()] 225 public string lifeTimeRate { get; set; } 226 227 [System.Xml.Serialization.XmlAttributeAttribute()] 228 public string lyTyChange { get; set; } 229 230 } 231 232 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 233 [System.SerializableAttribute()] 234 [System.ComponentModel.DesignerCategoryAttribute("code")] 235 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 236 public class storeRatePurchase 237 { 238 public string storeRate { get; set; } 239 } 240 241 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 242 [System.SerializableAttribute()] 243 [System.ComponentModel.DesignerCategoryAttribute("code")] 244 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 245 public class vipStatus 246 { 247 [System.Xml.Serialization.XmlAttributeAttribute()] 248 public string issueDate { get; set; } 249 250 [System.Xml.Serialization.XmlAttributeAttribute()] 251 public string issueShop { get; set; } 252 253 [System.Xml.Serialization.XmlAttributeAttribute()] 254 public string ptsToUpgrade { get; set; } 255 256 [System.Xml.Serialization.XmlAttributeAttribute()] 257 public string expiryDate { get; set; } 258 259 [System.Xml.Serialization.XmlAttributeAttribute()] 260 public string upgradeShop { get; set; } 261 262 [System.Xml.Serialization.XmlAttributeAttribute()] 263 public string ptsToRenew { get; set; } 264 } 265 266 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 267 [System.SerializableAttribute()] 268 [System.ComponentModel.DesignerCategoryAttribute("code")] 269 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 270 public class comments 271 { 272 [System.Xml.Serialization.XmlAttributeAttribute()] 273 public string comment { get; set; } 274 }
解析代码如下
1 private static System.Xml.Serialization.XmlSerializer Serializer; 2 /// <summary> 3 /// 指定XML字符串序列化成对象 4 /// </summary> 5 /// <typeparam name="T"></typeparam> 6 /// <param name="xml"></param> 7 /// <returns></returns> 8 public static T DeserializeForXml<T>(string xml) where T : class, new() 9 { 10 System.IO.StringReader stringReader = null; 11 try 12 { 13 Serializer = Serializer ?? new XmlSerializer(typeof(T)); 14 stringReader = new StringReader(xml); 15 T result = Serializer.Deserialize(stringReader) as T; 16 return result; 17 } 18 finally 19 { 20 if ((stringReader != null)) 21 { 22 stringReader.Dispose(); 23 } 24 } 25 }
调用方式:
1 var rpXML = AcxiomXMLHelper.DeserializeForXml<CustomerDetails.Response>(returnXML);
好了,接下来就出现了问题
departmentPurchase 下面的department始终是没有数据,调试好久都找不到问题出现在哪里。
尝试找解决的办法,先实例化一个Response对象序列化后写入文件,再将文件内容读出来反序列化出来
1 Response response = new Response 2 { 3 totalCount = "123", 4 resultCode = "ABC", 5 resultMessage = "测试", 6 profile = new profile { lastName = "李", firstName = "爽", dateOfBirth = "XX0816", age = "", gender = "1", address = "浙江省 杭州富阳市 东州工业园区3号路1号杭州龙盛工贸有限公", email = "htlslll@163.com", cellEmail = "", socialMedia = "", homePhone = "", cellPhone = "18857199925", contactabiltyMail = "1", contactabiltyEmail = "1", contactabiltyCellEmail = "0", contactabiltyHomePhone = "1", contactabiltyCellPhone = "1", contactabiltyText = "1", contactabiltySocialMedia = "0", vipLevel = "2", memberId = "OC540C00016824", saAccount = "660996", classa = "小姐", homeStoreCode = "OC54" }, 7 comments = new comments { comment = "第一场雪" }, 8 purchaseHistory = new purchaseHistory 9 { 10 departmentPurchase = new departmentPurchase 11 { 12 totalTYAmount = "21705", 13 totalTYUnitCnt = "9", 14 firstTxn = "20160713", 15 lastTxn = "20160829", 16 totalLifeTimeSale = "36791", 17 department = new List<department> { 18 new department { categoryName = "D08", tyAmount = "2970", tyUnitCnt = "2" }, 19 new department { categoryName = "D01", tyAmount = "9750", tyUnitCnt = "3" }, 20 new department { categoryName = "D02", tyAmount = "8985", tyUnitCnt = "4" } 21 } 22 }, 23 ratePurchase = new ratePurchase 24 { 25 totalLyAmount = "0", 26 totalLyRate = "0", 27 totalTyAmount = "21705", 28 totalTyRate = "100", 29 totalLifeTimeAmount = "36791", 30 totalLifeTimeRate = "100", 31 rate = new rate { categoryName = "Retail", lyAmount = "", lyRate = "0", lyToDate = "0", tyAmount = "21705", tyRate = "100", tyToDate = "21705", lifeTimeAmount = "36791", lifeTimeRate = "100", lyTyChange = "100" } 32 }, 33 storeRatePurchase = new storeRatePurchase { storeRate = string.Empty } 34 }, 35 vipStatus = new vipStatus { issueDate = "20140629", issueShop = "OC54", ptsToUpgrade = "21705", expiryDate = "20170731", upgradeShop = "", ptsToRenew = "8130" } 36 }; 37 38 FileStream stream = new FileStream(@"d:\xmlFormat.xml", FileMode.Create); 39 XmlSerializer xmlserilize = new XmlSerializer(typeof(Response)); 40 xmlserilize.Serialize(stream, response); stream.Close(); 41 42 43 44 using (FileStream xmlStream = new FileStream(@"d:\xmlFormat.xml", FileMode.Open)) 45 { 46 using (XmlReader xmlReader = XmlReader.Create(xmlStream)) 47 { 48 XmlSerializer serializer = new XmlSerializer(typeof(Response)); 49 Response res = serializer.Deserialize(xmlReader) as Response; 50 } 51 }
代码中res是反序列化的结果,数据都正确。这就有点恼火了,怎么办呢?
比较我生成的文件和API返回的XML:
下面是我生成的XML格式
1 <Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" totalCount="123" resultCode="ABC" resultMessage="测试"> 2 <profile lastName="李" firstName="爽" dateOfBirth="XX0816" age="" gender="1" address="浙江省 杭州富阳市 东州工业园区3号路1号杭州龙盛工贸有限公" email="htlslll@163.com" cellEmail="" socialMedia="" homePhone="" cellPhone="18857199925" contactabiltyMail="1" contactabiltyEmail="1" contactabiltyCellEmail="0" contactabiltyHomePhone="1" contactabiltyCellPhone="1" contactabiltyText="1" contactabiltySocialMedia="0" vipLevel="2" memberId="OC540C00016824" saAccount="660996" classa="小姐" homeStoreCode="OC54" /> 3 <purchaseHistory> 4 <departmentPurchase totalLifeTimeSale="36791" totalTYAmount="21705" lastTxn="20160829" totalTYUnitCnt="9" firstTxn="20160713"> 5 <department> 6 <department categoryName="D08" tyAmount="2970" tyUnitCnt="2" /> 7 <department categoryName="D01" tyAmount="9750" tyUnitCnt="3" /> 8 <department categoryName="D02" tyAmount="8985" tyUnitCnt="4" /> 9 </department> 10 </departmentPurchase> 11 <ratePurchase totalLyAmount="0" totalLyRate="0" totalTyAmount="21705" totalTyRate="100" totalLifeTimeAmount="36791" totalLifeTimeRate="100"> 12 <rate categoryName="Retail" lyAmount="" lyRate="0" lyToDate="0" tyAmount="21705" tyRate="100" tyToDate="21705" lifeTimeAmount="36791" lifeTimeRate="100" lyTyChange="100" /> 13 </ratePurchase> 14 <storeRatePurchase> 15 <storeRate /> 16 </storeRatePurchase> 17 </purchaseHistory> 18 <vipStatus issueDate="20140629" issueShop="OC54" ptsToUpgrade="21705" expiryDate="20170731" upgradeShop="" ptsToRenew="8130" /> 19 <comments comment="第一场雪" /> 20 </Response>
仔细比对发现问题
在departmentPurchase 节点下我多了一层department节点,可我是按照接口的结果定义的对象啊
1 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34209")] 2 [System.SerializableAttribute()] 3 [System.ComponentModel.DesignerCategoryAttribute("code")] 4 [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)] 5 public class departmentPurchase 6 { 7 [System.Xml.Serialization.XmlAttributeAttribute()] 8 public string totalTYAmount { get; set; } 9 10 [System.Xml.Serialization.XmlAttributeAttribute()] 11 public string totalTYUnitCnt { get; set; } 12 13 [System.Xml.Serialization.XmlAttributeAttribute()] 14 public string firstTxn { get; set; } 15 16 [System.Xml.Serialization.XmlAttributeAttribute()] 17 public string lastTxn { get; set; } 18 19 [System.Xml.Serialization.XmlAttributeAttribute()] 20 public string totalLifeTimeSale { get; set; } 21 22 [System.Xml.Serialization.XmlElementAttribute("department", typeof(List<department>), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)] 23 public List<department> department { get; set; } 24 }
怎么搞呢?在网上不停的找答案,最终都无解。但是没有放弃,答案也往往在快要放弃的时候出现
我尝试的修改了department的定义
修改前
1 [System.Xml.Serialization.XmlElementAttribute("department", typeof(List<department>), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)] 2 public List<department> department { get; set; }
修改后
1 [System.Xml.Serialization.XmlElementAttribute("department", typeof(department), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)] 2 public List<department> department { get; set; }
重新运行,奇迹出现
1 <?xml version="1.0"?> 2 <Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" totalCount="123" resultCode="ABC" resultMessage="测试"> 3 <profile lastName="李" firstName="爽" dateOfBirth="XX0816" age="" gender="1" address="浙江省 杭州富阳市 东州工业园区3号路1号杭州龙盛工贸有限公" email="htlslll@163.com" cellEmail="" socialMedia="" homePhone="" cellPhone="18857199925" contactabiltyMail="1" contactabiltyEmail="1" contactabiltyCellEmail="0" contactabiltyHomePhone="1" contactabiltyCellPhone="1" contactabiltyText="1" contactabiltySocialMedia="0" vipLevel="2" memberId="OC540C00016824" saAccount="660996" classa="小姐" homeStoreCode="OC54" /> 4 <purchaseHistory> 5 <departmentPurchase totalLifeTimeSale="36791" totalTYAmount="21705" lastTxn="20160829" totalTYUnitCnt="9" firstTxn="20160713"> 6 <department categoryName="D08" tyAmount="2970" tyUnitCnt="2" /> 7 <department categoryName="D01" tyAmount="9750" tyUnitCnt="3" /> 8 <department categoryName="D02" tyAmount="8985" tyUnitCnt="4" /> 9 </departmentPurchase> 10 <ratePurchase totalLyAmount="0" totalLyRate="0" totalTyAmount="21705" totalTyRate="100" totalLifeTimeAmount="36791" totalLifeTimeRate="100"> 11 <rate categoryName="Retail" lyAmount="" lyRate="0" lyToDate="0" tyAmount="21705" tyRate="100" tyToDate="21705" lifeTimeAmount="36791" lifeTimeRate="100" lyTyChange="100" /> 12 </ratePurchase> 13 <storeRatePurchase> 14 <storeRate /> 15 </storeRatePurchase> 16 </purchaseHistory> 17 <vipStatus issueDate="20140629" issueShop="OC54" ptsToUpgrade="21705" expiryDate="20170731" upgradeShop="" ptsToRenew="8130" /> 18 <comments comment="第一场雪" /> 19 </Response>
问题解决。
原因就出在解析XML节点的
typeof(department) 与 typeof(List<department>)