[.net 面向对象程序设计进阶] (11) 序列化(Serialization)(三) 通过接口 IXmlSerializable 实现XML序列化 及 通用XML类
本节导读:本节主要介绍通过序列化接口IXmlSerializable实现XML序列化和反序列化,整理了XML基础操作及序列化的通用类(包括XML及节点的基础读写操作,XML到DataSet\DataTable互转换操作,XML序列化及反序列化通用方法等)。
读前必备:
A.类和类的实例 [.net 面向对象编程基础] (9) 类和类的实例
B.类的成员 [.net 面向对象编程基础] (10) 类的成员(字段、属性、方法)
C.数组与集合 [.net 面向对象编程基础] (17) 数组与集合
E.LINQ使用 [.net 面向对象编程基础] (20) LINQ使用
1. 通过序列化接口IXmlSerializable实现XML序列化
命名空间:System.Xml.Serialization
接口:IXmlSerializable
方法:
XmlSchema GetSchema();
void ReadXml(XmlReader reader);
void WriteXml(XmlWriter writer);
下面通过示例介绍关于序列化接口的使用,还是通过博客园文章为例:
定义文章实体类及文章调用方法:
public class MyBlogs
{
/// <summary>
/// 获取我的博客园中文章
/// </summary>
/// <returns></returns>
public static List<MyArticle> GetMyArticle(int count)
{
var document = XDocument.Load(
"http://wcf.open.cnblogs.com/blog/u/yubinfeng/posts/1/" + count
);
List<MyArticle> myArticleList = new List<MyArticle>();
var elements = document.Root.Elements(); //在进行这个工作之前,我们先获取我博客中的文章列表
var result = elements.Where(m => m.Name.LocalName == "entry").Select(myArticle => new MyArticle
{
id = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "id").Value),
title = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "title").Value,
published = Convert.ToDateTime(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "published").Value),
updated = Convert.ToDateTime(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "updated").Value),
diggs = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "diggs").Value),
views = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "views").Value),
comments = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "comments").Value),
summary = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "summary").Value,
link = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "link").Attribute("href").Value,
author = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "author").Elements().SingleOrDefault(x => x.Name.LocalName == "name").Value
}).OrderByDescending(m => m.published);
myArticleList.AddRange(result);
return myArticleList;
}
}
/// <summary
/// 我的博客文章实体类
/// </summary> public class MyArticle
{
/// <summary>
/// 文章编号
/// </summary>
public int id { get; set; }
/// <summary>
/// 文章标题
/// </summary>
public string title { get; set; } /// <summary>
/// 文章摘要
/// </summary>
public string summary { get; set; } /// <summary>
/// 发布时间
/// </summary>
public DateTime published { get; set; }
/// <summary>
/// 最后更新时间
/// </summary>
public DateTime updated { get; set; }
/// <summary>
/// URL地址
/// </summary>
public string link { get; set; }
/// <summary>
/// 推荐数
/// </summary>
public int diggs { get; set; }
/// <summary>
/// 浏览量
/// </summary>
public int views { get; set; } /// <summary>
/// 评论数
/// </summary>
public int comments { get; set; } /// <summary>
/// 作者
/// </summary>
public string author { get; set; }
}
XML通过接口序列化和反序列化的方法
/// <summary>
/// 序列化XML 对象=》XML文本
/// 下面注释项,可根据需要使用
/// </summary>
/// <param name="Obj"></param>
/// <returns></returns>
public static string ObjectToXmlSerializer(Object Obj)
{
string XmlString = "";
XmlWriterSettings settings = new XmlWriterSettings();
//settings.OmitXmlDeclaration = true;//去除xml声明
settings.Encoding = Encoding.Default;//使用默认编码
//settings.IndentChars = "--"; //使用指定字符缩进
settings.Indent = true; //换行缩进 using (System.IO.MemoryStream mem = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(mem, settings))
{
//去除默认命名空间xmlns:xsd和xmlns:xsi
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", ""); XmlSerializer formatter = new XmlSerializer(Obj.GetType());
formatter.Serialize(writer, Obj, ns);
}
XmlString = Encoding.Default.GetString(mem.ToArray());
}
return XmlString;
} /// <summary>
/// 反序列化 XML文本=》对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <returns></returns>
public static T ObjectToXmlDESerializer<T>(string str) where T : class
{
object obj;
using (System.IO.MemoryStream mem = new MemoryStream(Encoding.Default.GetBytes(str)))
{
using (XmlReader reader = XmlReader.Create(mem))
{
XmlSerializer formatter = new XmlSerializer(typeof(T));
obj = formatter.Deserialize(reader);
}
}
return obj as T;
}
调用如下:
//命名空间:System.Xml.Serialization
//接口:IXmlSerializable
//方法:XmlSchema GetSchema();void ReadXml(XmlReader reader);void WriteXml(XmlWriter writer); //(1)获取我博客园中最后10篇文章 (实际上这个过程也是反序列化)
List<MyArticle> myArticleList = MyBlogs.GetMyArticle(); //序列化并输出XML文本
string xmlString = ObjectToXmlSerializer(myArticleList);
Console.Write(xmlString); //序列化XML文本,遍历输出对象
List<MyArticle> myNewArticleList = ObjectToXmlDESerializer<List<MyArticle>>(xmlString); //遍历输出反序化的新对象myNewArticleList
myNewArticleList.ForEach(m =>
Console.WriteLine("文章编号:" + m.id + "\n文章标题:" + m.title)
);
运行结果如下:
2. XML类
我们在序列化XML的时候,经常要操作XML,下面我列出XML类的一些成员,供参考查阅
XML操作的命名空间:System.Xml;
名称 |
描述 |
XmlAttribute |
表示一个特性对象的集合,这些对象控制XmlSerializer如何序列化和反序列化对象 |
XmlArrayAttribute |
指定XmlSerializer应将特定的类成员序列化为XML元素数组 |
XmlArrayItemAttribute |
指定XmlSerializer可以放置在序列化数组中的派生类型 |
XmlArrayItemAttributes |
表示XmlArrayItemAttribute对象的集合 |
XmlAttributeAttribute |
指定XmlSerializer应将类成员作为XML特性序列化 |
XmlChoiceIdentifierAttribute |
指定可以通过使用枚举来进一步消除成员的歧义 |
XmlElementAttribute |
在XmlSerializer序列化或反序列化包含对象时,指示公共字段或属性表示XML元素 |
XmlElementAttributes |
表示XmlElementAttribute的集合,XmlSerializer将其用于它重写序列化类的默认方式 |
XmlEnumAttribute |
控制XmlSerializer如何序列化枚举成员 |
XmlIgnoreAttribute |
指示XmlSerializer方法不序列化公共字段或公共读/写属性值 |
XmlIncludeAttribute |
允许XmlSerializer在它序列化或反序列化对象时识别类型 |
XmlRootAttribute |
控制视为XML根元素的属性目标的XML序列化 |
XmlTextAttribute |
当序列化或反序列化时,想XmlSerializer指示应将此成员作为XML文本处理 |
XmlTypeAttribute |
控制当属性目标由XmlSerializer序列化时生成的XML结构 |
XmlAnyAttributeAttribute |
指定成员(返回XmlAttribute对象的数组的字段)可以包含XML属性 |
XmlAnyElementAttribute |
指定成员可以包含对象,该对象表示在序列化或反序列化的对象中没有相应成员的所有XML元素 |
XmlAnyElementAttributes |
表示XmlAnyElementAttribute对象的集合 |
XmlAttributeEventArgs |
为UnKnowAttribute提供数据 |
XmlAttributeOverrides |
允许你在使用XmlSerializer序列化或反序列化时重写属性、字段和类特性 |
XmlElementEventArgs |
为UnknownElement事件提供数据 |
XmlNamespaceDeclarationsAttribute |
指定目标属性、参数、返回值或类成员包含与XML文档中所用命名空间关联的前缀 |
XmlNodeEventArgs |
为UnknownNode时间提供数据 |
XmlSerializer |
将对象序列化到XML文档中和从XML文档中反序列化对象,XmlSerializer使你得以控制如何将对象编码到XML中 |
XmlSerializerNamespaces |
包含XmlSerializer用于在XML文档实例中生成限定名的XML命名空间和前缀 |
XmlTypeMapping |
包含从一种类型到另一种类型的映射 |
更多更详细的说明,请看官方API:http://msdn.microsoft.com/zh-cn/library/System.Xml.Serialization(v=vs.110).aspx
3. XML封装类
最后整理一个XML的封装类提供给小伙伴们,里面包含了XML节点到DataSet,DataTable及XML序列化和反序列化,XML写入文件或读取XML文件及节点等。
文件名:XmlHelper.cs
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Linq; namespace Common
{
/// <summary>
/// Xml通用类
/// Author:YuBinfeng
/// Data:2015/07/10
/// </summary>
public class XmlHelper
{ #region XML的基础读写 #region 将XML文本写入到指定路径的文件
/// <summary>
/// 将XML文本写入到指定路径的文件
/// </summary>
/// <param name="XMLString"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static bool WriteXmlString(string XMLString,string filePath)
{
try
{
File.WriteAllText(filePath, XMLString,Encoding.Default);
return true;
}
catch
{
return false;
}
}
#endregion #region 从指定的路径读取XML文本
/// <summary>
/// 将XML文本写入到指定路径的文件
/// </summary>
/// <param name="XMLString"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static string ReadXmlString( string filePath)
{
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
return xmlDoc.InnerXml;
}
catch (Exception ex)
{
return "";
}
}
#endregion #region 读取XML资源中的指定节点内容
/// <summary>
/// 读取XML资源中的指定节点内容
/// </summary>
/// <param name="source">XML资源</param>
/// <param name="xmlType">XML资源类型:文件,字符串</param>
/// <param name="nodeName">节点名称</param>
/// <returns>节点内容</returns>
public static object GetNodeValue(string source, XmlType xmlType, string nodeName)
{
XmlDocument xd = new XmlDocument();
if (xmlType == XmlType.File)
{
xd.Load(source);
}
else
{
xd.LoadXml(source);
}
XmlElement xe = xd.DocumentElement;
XmlNode xn = xe.SelectSingleNode("//" + nodeName);
if (xn != null)
{
return xn.InnerText;
}
else
{
return null;
}
} /// <summary>
/// 读取XML资源中的指定节点内容
/// </summary>
/// <param name="source">XML资源</param>
/// <param name="nodeName">节点名称</param>
/// <returns>节点内容</returns>
public static object GetNodeValue(string source, string nodeName)
{
if (source == null || nodeName == null || source == "" || nodeName == "" || source.Length < nodeName.Length * )
{
return null;
}
else
{
int start = source.IndexOf("<" + nodeName + ">") + nodeName.Length + ;
int end = source.IndexOf("</" + nodeName + ">");
if (start == - || end == -)
{
return null;
}
else if (start >= end)
{
return null;
}
else
{
return source.Substring(start, end - start);
}
}
}
#endregion #region 更新XML文件中的指定节点内容
/// <summary>
/// 更新XML文件中的指定节点内容
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="nodeName">节点名称</param>
/// <param name="nodeValue">更新内容</param>
/// <returns>更新是否成功</returns>
public static bool UpdateNode(string filePath, string nodeName, string nodeValue)
{
bool flag = false; XmlDocument xd = new XmlDocument();
xd.Load(filePath);
XmlElement xe = xd.DocumentElement;
XmlNode xn = xe.SelectSingleNode("//" + nodeName);
if (xn != null)
{
xn.InnerText = nodeValue;
flag = true;
}
else
{
flag = false;
}
return flag;
}
#endregion #region 操作xml文件中指定节点的数据
/// <summary>
/// 获得xml文件中指定节点的节点数据
/// </summary>
/// <param name="TableName"></param>
/// <returns></returns>
public static string GetNodeInfoByNodeName(string path, string nodeName)
{
string XmlString = "";
XmlDocument xml = new XmlDocument();
xml.Load(path);
System.Xml.XmlElement root = xml.DocumentElement;
System.Xml.XmlNode node = root.SelectSingleNode("//" + nodeName);
if (node != null)
{
XmlString = node.InnerText;
}
return XmlString;
}
#endregion
#endregion #region 共有属性
/// <summary>
/// XML资源类型
/// </summary>
public enum XmlType
{
File,
String
};
#endregion #region XML与DataSet DataTable相关 #region 读取XML资源到DataSet中
/// <summary>
/// 读取XML资源到DataSet中
/// </summary>
/// <param name="source">XML资源,文件为路径,否则为XML字符串</param>
/// <param name="xmlType">XML资源类型</param>
/// <returns>DataSet</returns>
public static DataSet GetDataSet(string source, XmlType xmlType)
{
DataSet ds = new DataSet();
if (xmlType == XmlType.File)
{
ds.ReadXml(source);
}
else
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(source);
XmlNodeReader xnr = new XmlNodeReader(xd);
ds.ReadXml(xnr);
}
return ds;
} #endregion #region 获取一个字符串xml文档中的ds
/// <summary>
/// 获取一个字符串xml文档中的ds
/// </summary>
/// <param name="xml_string">含有xml信息的字符串</param>
public static void get_XmlValue_ds(string xml_string, ref DataSet ds)
{
System.Xml.XmlDocument xd = new XmlDocument();
xd.LoadXml(xml_string);
XmlNodeReader xnr = new XmlNodeReader(xd);
ds.ReadXml(xnr);
xnr.Close();
int a = ds.Tables.Count;
}
#endregion #region 读取XML资源到DataTable中
/// <summary>
/// 读取XML资源到DataTable中
/// </summary>
/// <param name="source">XML资源,文件为路径,否则为XML字符串</param>
/// <param name="xmlType">XML资源类型:文件,字符串</param>
/// <param name="tableName">表名称</param>
/// <returns>DataTable</returns>
public static DataTable GetTable(string source, XmlType xmlType, string tableName)
{
DataSet ds = new DataSet();
if (xmlType == XmlType.File)
{
ds.ReadXml(source);
}
else
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(source);
XmlNodeReader xnr = new XmlNodeReader(xd);
ds.ReadXml(xnr);
}
return ds.Tables[tableName];
}
#endregion #region 读取XML资源中指定的DataTable的指定行指定列的值
/// <summary>
/// 读取XML资源中指定的DataTable的指定行指定列的值
/// </summary>
/// <param name="source">XML资源</param>
/// <param name="xmlType">XML资源类型:文件,字符串</param>
/// <param name="tableName">表名</param>
/// <param name="rowIndex">行号</param>
/// <param name="colName">列名</param>
/// <returns>值,不存在时返回Null</returns>
public static object GetTableCell(string source, XmlType xmlType, string tableName, int rowIndex, string colName)
{
DataSet ds = new DataSet();
if (xmlType == XmlType.File)
{
ds.ReadXml(source);
}
else
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(source);
XmlNodeReader xnr = new XmlNodeReader(xd);
ds.ReadXml(xnr);
}
return ds.Tables[tableName].Rows[rowIndex][colName];
}
#endregion #region 读取XML资源中指定的DataTable的指定行指定列的值
/// <summary>
/// 读取XML资源中指定的DataTable的指定行指定列的值
/// </summary>
/// <param name="source">XML资源</param>
/// <param name="xmlType">XML资源类型:文件,字符串</param>
/// <param name="tableName">表名</param>
/// <param name="rowIndex">行号</param>
/// <param name="colIndex">列号</param>
/// <returns>值,不存在时返回Null</returns>
public static object GetTableCell(string source, XmlType xmlType, string tableName, int rowIndex, int colIndex)
{
DataSet ds = new DataSet();
if (xmlType == XmlType.File)
{
ds.ReadXml(source);
}
else
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(source);
XmlNodeReader xnr = new XmlNodeReader(xd);
ds.ReadXml(xnr);
}
return ds.Tables[tableName].Rows[rowIndex][colIndex];
}
#endregion #region 将DataTable写入XML文件中
/// <summary>
/// 将DataTable写入XML文件中
/// </summary>
/// <param name="dt">含有数据的DataTable</param>
/// <param name="filePath">文件路径</param>
public static void SaveTableToFile(DataTable dt, string filePath)
{
DataSet ds = new DataSet("Config");
ds.Tables.Add(dt.Copy());
ds.WriteXml(filePath);
}
#endregion #region 将DataTable以指定的根结点名称写入文件
/// <summary>
/// 将DataTable以指定的根结点名称写入文件
/// </summary>
/// <param name="dt">含有数据的DataTable</param>
/// <param name="rootName">根结点名称</param>
/// <param name="filePath">文件路径</param>
public static void SaveTableToFile(DataTable dt, string rootName, string filePath)
{
DataSet ds = new DataSet(rootName);
ds.Tables.Add(dt.Copy());
ds.WriteXml(filePath);
}
#endregion #region 使用DataSet方式更新XML文件节点
/// <summary>
/// 使用DataSet方式更新XML文件节点
/// </summary>
/// <param name="filePath">XML文件路径</param>
/// <param name="tableName">表名称</param>
/// <param name="rowIndex">行号</param>
/// <param name="colName">列名</param>
/// <param name="content">更新值</param>
/// <returns>更新是否成功</returns>
public static bool UpdateTableCell(string filePath, string tableName, int rowIndex, string colName, string content)
{
bool flag = false;
DataSet ds = new DataSet();
ds.ReadXml(filePath);
DataTable dt = ds.Tables[tableName]; if (dt.Rows[rowIndex][colName] != null)
{
dt.Rows[rowIndex][colName] = content;
ds.WriteXml(filePath);
flag = true;
}
else
{
flag = false;
}
return flag;
}
#endregion #region 使用DataSet方式更新XML文件节点
/// <summary>
/// 使用DataSet方式更新XML文件节点
/// </summary>
/// <param name="filePath">XML文件路径</param>
/// <param name="tableName">表名称</param>
/// <param name="rowIndex">行号</param>
/// <param name="colIndex">列号</param>
/// <param name="content">更新值</param>
/// <returns>更新是否成功</returns>
public static bool UpdateTableCell(string filePath, string tableName, int rowIndex, int colIndex, string content)
{
bool flag = false; DataSet ds = new DataSet();
ds.ReadXml(filePath);
DataTable dt = ds.Tables[tableName]; if (dt.Rows[rowIndex][colIndex] != null)
{
dt.Rows[rowIndex][colIndex] = content;
ds.WriteXml(filePath);
flag = true;
}
else
{
flag = false;
}
return flag;
}
#endregion #endregion #region XML序列化与反序列化相关 /// <summary>
/// 序列化XML 对象=》XML文本
/// 下面注释项,可根据需要使用
/// </summary>
/// <param name="Obj"></param>
/// <returns></returns>
public static string ObjectToXmlSerializer(Object Obj)
{
string XmlString = "";
XmlWriterSettings settings = new XmlWriterSettings();
//settings.OmitXmlDeclaration = true;//去除xml声明
settings.Encoding = Encoding.Default;//使用默认编码
//settings.IndentChars = "--"; //使用指定字符缩进
settings.Indent = true; //换行缩进 using (System.IO.MemoryStream mem = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(mem, settings))
{
//去除默认命名空间xmlns:xsd和xmlns:xsi
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", ""); XmlSerializer formatter = new XmlSerializer(Obj.GetType());
formatter.Serialize(writer, Obj, ns);
}
XmlString = Encoding.Default.GetString(mem.ToArray());
}
return XmlString;
} /// <summary>
/// 反序列化 XML文本=》对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <returns></returns>
public static T ObjectToXmlDESerializer<T>(string str) where T : class
{
object obj;
using (System.IO.MemoryStream mem = new MemoryStream(Encoding.Default.GetBytes(str)))
{
using (XmlReader reader = XmlReader.Create(mem))
{
XmlSerializer formatter = new XmlSerializer(typeof(T));
obj = formatter.Deserialize(reader);
}
}
return obj as T;
} #endregion }
}
4. 本节要点:
A.本节主要介绍了通过序列化接口IXmlSerializable实现XML序列化
B.XML本身的操作简单介绍
C.最后提供了一个序列化及XML操作的通用类
==============================================================================================
<如果对你有帮助,记得点一下推荐哦,如有有不明白或错误之处,请多交流>
<对本系列文章阅读有困难的朋友,请先看《.net 面向对象编程基础》>
<转载声明:技术需要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>
.NET 技术交流群:467189533
==============================================================================================