C# XML序列化/反序列化参考
.NET提供了很不错的XML序列化/反序列化器,(它们所在的命名空间为System.Xml.Serialization)这是很方便的,下面对它的使用做一些总结,以供参考。
1,简单序列化
public static string SerializeXml(object data) {
using (StringWriter sw = new StringWriter()) {
XmlSerializer xz = new XmlSerializer(data.GetType());
xz.Serialize(sw, data);
return sw.ToString();
}
}
以上代码是序列化为字符串,如果需要以流的形式返回序列化结果给客户端,或写入文件,那么通常需要选择一种编码,常见的编码格式是UTF-8,但某些特殊场合也许你会被要求使用GB2312编码,下面例子是使用GB2312编码的情况:
public static MemoryStream SerializeXml(object data) {
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms, Encoding.GetEncoding("GB2312"));
XmlSerializer xz = new XmlSerializer(data.GetType());
xz.Serialize(sw, data);
return ms;
}
这样就直接把对象以特定编码格式序列化到MemoryStream里去了,当然也许你想到了,先使用前面的SerializeXml生成字符串,再把字符串以特定编码格式写到流或者字节数组中去不行吗?当然行,不过这样会多出一步,不够直接。
这里还有个要注意的地方,序列化到流的时候,不要对Stream及TextWriter对象包在using里,因为这样会导致流返回的时候已经被关闭。
2,简单反序列化
FileStream fs = File.Open("file.xml", FileMode.Open);
using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) {
XmlSerializer xz = new XmlSerializer(typeof(Department));
Department dept = (Department)xz.Deserialize(sr);
//blah blah ...
}
其中Department是你要反序列化出来的类,同样需要注意编码,这里指定的是UTF-8,但不排除有别的可能。
其实序列化和反序列化时可逆的,你通过怎样的类和编码把对象序列化成xml,就能通过怎样的类和编码将xml反序列化成对象。
3,指定XML标签的名字
[XmlRoot("department")]
public class Department {
public string DeptName { get; set; } [XmlElement("extra")]
public DeptExtraInfo DeptExtraInfo { get; set; }
}
通过XmlRoot注解和XmlElement注解即可实现,其中XmlRoot用于指定“根”,也就是XML的最上一层的Tag。
4,指定XML标签的属性
[XmlRoot("department")]
public class Department {
public string DeptName { get; set; } = "研发部"; [XmlAttribute("timestamp")]
public int Timestamp = ;
}
利用XmlAttribute注解,这么一来,Timestamp就成为了department这个根节点的timestamp属性。
5,去掉不需要的namespace
默认情况下,xml的头会带上类似这样的一个namespace:
<department xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- blah blah blah -->
</department>
你不需要的话可以修改一下序列化方法:
public static string SerializeXml(object data) {
using (Utf8Writer sw = new Utf8Writer()) {
XmlSerializer xz = new XmlSerializer(data.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
xz.Serialize(sw, data, ns);
return sw.ToString();
}
}
6,序列化集合的时候不要“再包一层”
这个怎么说呢?先看这么一个类:
[XmlRoot("department")]
public class Department {
public string DeptName { get; set; }; public List<Employee> Details { get; set; };
}
序列化出来的结果是:
<?xml version="1.0" encoding="utf-8"?>
<department>
<DeptName>研发部</DeptName>
<Employees>
<Employee>
<EmpName>张三</EmpName>
<EmpSalary>10000</EmpSalary>
</Employee>
<Employee>
<EmpName>李四</EmpName>
<EmpSalary>8000</EmpSalary>
</Employee>
</Employees>
</department>
注意Employee这个标签外面包了一层Employees,这个也许不是你想要的结果,这才是你想要的结果:
<?xml version="1.0" encoding="utf-8"?>
<department>
<DeptName>研发部</DeptName>
<Employee>
<EmpName>张三</EmpName>
<EmpSalary>10000</EmpSalary>
</Employee>
<Employee>
<EmpName>李四</EmpName>
<EmpSalary>8000</EmpSalary>
</Employee>
</department>
这个怎么做呢?很简单,在Employees前面加个XmlElement注解即可:
[XmlRoot("department")]
public class Department {
public string DeptName { get; set; } = "研发部"; [XmlElement("Employee")]
public List<Employee> Employees { get; set; } = new List<Employee>();
}
另外,如果是只是想改一下之前的Employees标签的名字的话,用这样一个注解:[XmlArray("NewName")]。
7,序列化null值属性
默认情况下,null值的属性是不会被序列化的,想想看为什么?
因为生成<DeptName />这样的序列化结果的话,没办法知道DeptName到底是null还是空字符串,所以比较好的解决方法是在序列化之前,把null字符串填充为空字符串。可以考虑写一个帮助方法,利用反射遍历一个对象里的所有字符串属性,将null设置为空字符串,当然了,实际的情况要考虑得更全面点,比如对象里还有对象,而且还包含可枚举对象的情况,估计得使用递归。篇幅问题,代码我就不贴了。
另外还有一种比较地道的做法,不需要改变对象的值,那就是在对象上加上[XmlElement(IsNullable = true)]注解,但这样带来的问题就是会在序列化生成的tag中多出一个xsi:nil="true"这样的属性来。
8,手工反序列化
有些情况实在太特殊,没办法直接用简单的Deserialize方法来反序列化,例如这个XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:DeliveryAddressUpdate_S10 xmlns:ns0="urn:ABC:GAIA:CN:LoadSetNoAndChineseDelAddr:ISC0186">
<Line>
<ASNNNB>95175154 </ASNNNB>
<CHDANR>00476</CHDANR>
<ASCUID>SHD3SHD3</ASCUID>
<IGAAUC>上海</IGAAUC>
<IGAAUC>闵行区</IGAAUC>
<IGAAUC>七莘路8888号</IGAAUC>
<IGAAUC>XXXX大楼XXXX室</IGAAUC>
</Line>
<Line>
<ASNNNB>124321 </ASNNNB>
<CHDANR>4321</CHDANR>
<ASCUID>4312</ASCUID>
<IGAAUC>上海</IGAAUC>
<IGAAUC>浦东新区</IGAAUC>
<IGAAUC>浦东大道9999号</IGAAUC>
<IGAAUC>YYYY大楼YYYY室</IGAAUC>
</Line>
</ns0:DeliveryAddressUpdate_S10>
首先根节点很奇葩,默认反序列化器不认,另外就是IGAAUC,重复多次,它的意图是说重复的这几个IGAAUC拼接在一起,生成一个地址,这个默认的反序列化显然做不到,手工读吧,参考代码如下:
List<Address> addrList = new List<Address>();
Address currentAddress = new Address();
XmlTextReader reader = new XmlTextReader(new MemoryStream(File.ReadAllBytes("test.xml")));
while (reader.Read()) {
if (reader.IsStartElement()) {
switch (reader.Name) {
case "Line":
currentAddress = new Address();
addrList.Add(currentAddress);
break;
case "ASNNNB":
currentAddress.Asnnb = reader.ReadString();
break;
case "CHDANR":
currentAddress.Chdanr = reader.ReadString();
break;
case "ASCUID":
currentAddress.Ascuid = reader.ReadString();
break;
case "IGAAUC":
currentAddress.Igaauc += reader.ReadString().Trim() + "\r\n";
break;
}
}
}
//addrList便是结果
C# XML序列化/反序列化参考的更多相关文章
- C# Json库 和 xml 序列化反序列化 存在的问题
json 正常情况下不会对私有成员进行序列化和反序列化, 因此在用json做深拷贝时, 就会丢失数据. 解决办法: 声明成公有成员. json在序列化和反序列化时, 如果类中有IComma ...
- php json与xml序列化/反序列化
在web开发中对象的序列化与反序列化经常使用,比较主流的有json格式与xml格式的序列化与反序列化,今天想写个jsop的小demo,结果发现不会使用php序列化,查了一下资料,做个笔记 简单数组js ...
- XML序列化反序列化—常用类
public class XMLSerializer { #region (public) xml序列化 /// <summary> /// ...
- C# 复杂格式多级深度XML序列化反序列化
default.xml 文件如下: <config><partnerships> <partnership name="Main_Listener" ...
- C# XML序列化/反序列化类XmlSerializer使用示例
using System; using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; ...
- XML序列化反序列化
using System; using System.Collections.Generic; using System.IO; using System.Xml.Serialization; nam ...
- XML序列化/反序列化数据库形式保存和读取。
直接上码: 首先创建class1类 public class Class1 { public string name { get; set; } public int age { get; set; ...
- C# WPF xml序列化 反序列化
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- XML序列化与反序列化接口对接实战,看这篇就够了
关键字:c# .NET XML 序列化 反序列化 本文为接口对接实践经验分享,不对具体的XML概念定义进行阐述:涉及工具类及处理方法已在生产环境使用多年,可放心使用.当然如果你发现问题,或有不同想法, ...
随机推荐
- 关于多条数据转为json格式单次传输的问题 2017.05.27
数据形式如下: var mycars = [];//定义数组存放多条数据 for(var i=0;i<2;i++){ var jsonData = {};//定义变量存放单条数据 jsonDat ...
- vue的传参方式和router使用技巧
vue传参方法一 1,路由配置 { path: '/describe/:id', name: 'Describe', component: Describe } 2,使用方法 // 直接调用$rout ...
- MySQL数据库简识
MySQL:关系型数据库 (由瑞典MySQL AB公司开发,后来被Sun公司收购,Sun公司后来又被Oracle公司收购,目前属于Oracle旗下产品) 开源 免费 不要钱 ...
- Linux用户和组管理,添加修改用户,添加修改组,加入组,移除组
1.安全介绍3A Authentication: 认证,用户名和对应口令 Authorization: 授权,不同用户权限不同 Accouting/Audition: 审计 2. 所属者和所属组 us ...
- 用beego开发服务端应用
用beego开发服务端应用 说明 Quick Start 安装 创建应用 编译运行 打包发布 代码生成 开发文档 目录结构说明 使用配置文件 beego默认参数 路由设置 路由的表述方式 直接设置路由 ...
- netData.go 阅读源码
) // 定义数据传输结构 type NetData struct { // 消息体 Body interface{} // 操作代号 Operation string ...
- js生成带logo的二维码
作为一名java程序员,一直以来都是使用服务端生成二维码,最近接触前端的设计,感觉二维码这块如果放到前端去生成,一方面可以减轻服务端的压力,访问带宽,另一方面,前端页面控制比较顺畅 闲话少叙,说下我的 ...
- BZOJ_1500_[NOI2005]维修数列_splay
BZOJ_1500_[NOI2005]维修数列_splay 题意: 分析: 节点维护从左开始的最大连续子段和,从右开始的最大连续子段和,区间的最大连续子段和 插入:重新建一棵树,把pos旋到根,把po ...
- 操作系统--进程管理(Processing management)
一.进程的组成 进程通常由程序.数据和进程控制块(Process Control Block,PCB)组成. 二. 进程的状态以及状态切换 进程执行时的间断性决定了进程可能具有多种状态,最基本的三种状 ...
- ISCC2018(最新的考核解析)
最近一直在做这个 ISCC2018,感觉可能自己只是一个新手吧!但是我会继续努力的,希望我的解题思路能够给你们带来一定的想法,我也希望自己能够在安全方面遇到更多志同道合的人! 其它题目可以看这里 1 ...