C# XML 序列化与反序列化
简介与实现
.NET提供了很不错的XML序列化/反序列化器
所在命名空间:System.Xml.Serialization
- 封装实现代码
using System;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace Unified.Services.Core
{
public class XmlSerializerHelper
{
/// <summary>
/// 将XML序列化为实体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xmlObj"></param>
/// <returns></returns>
public static T DeserializeXML<T>(string xmlObj)
{
XmlSerializer serializer = new XmlSerializer(typeof(T),new XmlRootAttribute("response"));
using (StringReader reader = new StringReader(xmlObj))
{
return (T)serializer.Deserialize(reader);
}
}
/// <summary>
/// 将对象序列化为xml
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string SerializeXml(object data)
{
using (StringWriter sw = new StringWriter())
{
XmlSerializer xz = new XmlSerializer(data.GetType());
xz.Serialize(sw, data);
XElement xmlDocumentWithoutNs = RemoveAllNamespaces(XElement.Parse(sw.ToString()));
return xmlDocumentWithoutNs.ToString();
}
}
/// <summary>
/// 删除命名空间
/// </summary>
/// <param name="xmlDocument"></param>
/// <returns></returns>
private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
return new XElement(xmlDocument.Name.LocalName,
xmlDocument.Attributes()
.Where(a => !a.IsNamespaceDeclaration)
.Select(a => new XAttribute(a.Name.LocalName, a.Value)),
xmlDocument.Nodes().Select(n =>
n is XElement child ? RemoveAllNamespaces(child) : n));
}
}
}
注意事项
xml 字符串验证
/// <summary>
/// Xml字符串格式验证
/// </summary>
/// <param name="xmlString">Xml字符串</param>
/// <returns></returns>
public static bool IsValidXml(string xmlString)
{
try
{
// 创建XmlDocument对象,加载xml字符串
new XmlDocument().LoadXml(xmlString);
// 如果没有异常,则说明xml字符串是有效的
return true;
}
catch (XmlException)
{
// 如果有异常,则说明xml字符串是无效的
return false;
}
}
实体序列化为 xml
序列化集合的时候不要“再包一层”
[XmlRoot("department")]
public class Department {
public string DeptName { get; set; }
[XmlElement("Employee")]
public List<Employee> Details { get; set; }
}
xml序列化与json序列化不一样,顶级标签名是当前实体的 Class Name 所以需要进行特性标注[XmlRoot("elementName")],标注之后当前类的 Class Name 就成了序列化之后xml的顶级标签名。
List 集合类型序列化也同样需要进行标注,如上。
双标签序列化
空元素可能输出为
<Name />,与<Name></Name>在 XML 语义上等价。null属性通常被省略;[XmlElement(IsNullable = true)]可输出xsi:nil。如对接协议强制要求双标签,应单独控制 XML 写出方式,本辅助类不保证这种格式。
删除命名空间
xml 序列化之后默认会有类似下面这种,带有 namespace 的内容
<department xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- blah blah blah -->
</department>
实现代码中的
RemoveAllNamespaces()方法就是用来删除 namespace 的
xml 序列化为实体
xml 序列化为实体需要注意的是顶级标签 XmlRootAttribute("elementName") 这里默认是添加了指定顶级标签名的
示例约定
反序列化方法把根节点固定为 response,仅适用于对应协议;使用 department 等模型时,应改为匹配的根名称,或使用 new XmlSerializer(typeof(T)) 读取模型上的 [XmlRoot]。Employee 为业务模型,需要自行定义,并引入 System.Collections.Generic。[XmlElement("Employee")] 将集合项直接输出到父节点;需要集合外层标签时使用 XmlArray 与 XmlArrayItem。
删除命名空间只适用于明确不使用命名空间的协议:同名、不同命名空间的属性可能冲突,xsi:nil 等语义也可能丢失,常规序列化建议保留命名空间。本示例的 XML 验证只检查语法,不验证 XSD 或业务字段。
参考:使用特性控制 XML 序列化。

浙公网安备 33010602011771号