XmlSerializer 序列化与反序列化CDATA 以及实现
2015-10-26 17:06
381 查看
XmlSerializer类可以帮助我们将对象的状态序列化对保存,同时通过反序列化,可以还原对象的状态。通过与XML序列化与反序列化相关的特性(Attribute),可以控制我们的序列化的XML格式;同时通过实现IXmlSerializable接口,可以自定义的实现序列化与反序列化。关于此类,详情查看MSDN
XmlSerializer类。不过在一些特殊情况下,CDATA类型的序列化与反序列化并不那么容易,或者说会出现一定的问题,本文将对此进行探讨。
1,新建测试项目和窗体
窗体代码如下:
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializerTest
{
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
private void buttonSerialize_Click(object sender, EventArgs e)
{
var tc = new TestClass();
tc.ID = 2011;
tc.CDataContent = @"<table id=""test"">test";
var serializer = new XmlSerializer(tc.GetType());
var text = new StringBuilder();
using (var s = new StringWriter(text))
{
serializer.Serialize(s, tc);
}
this.textBoxXml.Text = text.ToString();
}
private void buttonDeserialize_Click(object sender, EventArgs e)
{
var serializer = new XmlSerializer(typeof(TestClass));
using (var s = new StringReader(this.textBoxXml.Text))
{
var tc = serializer.Deserialize(s) as TestClass;
if (tc != null)
{
MessageBox.Show(tc.CDataContent);
}
}
}
/// <summary>
/// Test class
/// </summary>
[Serializable]
public class TestClass
{
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Content")]
public string CDataContent { get; set; }
}
}
}
运行,点击Serialize按钮,可以得到序列化生成的XML文档:
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>2011</ID>
<Content><table id="test">test</Content>
</TestClass>
点击Deserialize按钮,可以得到以下结果:
---------------------------
---------------------------
<table id="test">test
---------------------------
OK
---------------------------
2,序列化为CDATA
如果需要将序列化生成的XML转化为以下格式(在实际中往往我们需要的是这种效果,而不是被转义的字符):
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>2011</ID>
<Content>
<![CDATA[
<table id="test">test]]>
</Content>
</TestClass>
这个时候我们至少有两种方法来实现。
2.1,修改实体类
我们将实体类TestClass修改为以下(关于为什么需要这样定义,请大家自行思考):
/// <summary>
/// Test class
/// </summary>
[Serializable]
public class TestClass
{
[XmlElement("ID")]
public int ID { get; set; }
[XmlIgnore]
public string CDataContent { get; set; }
[XmlElement("Content")]
public XmlNode[] Nodes
{
get
{
var dom = new XmlDocument();
return new XmlNode[] { dom.CreateCDataSection(this.CDataContent) };
}
set
{
if (value == null)
{
this.CDataContent = null;
return;
}
if (value.Length != 1)
throw new InvalidOperationException("Invalid array.");
var content = value[0];
if (null == content)
throw new InvalidOperationException("Node is null.");
this.CDataContent = content.Value;
}
}
}
运行后,TextBox的内容为:
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>2011</ID>
<Content><![CDATA[<table id="test">test]]></Content>
</TestClass>
已经实现。
2.2,实现IXmlSerializable接口
/// <summary>
/// Test class
/// </summary>
[Serializable]
public class TestClass : IXmlSerializable
{
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Content")]
public string CDataContent { get; set; }
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(XmlReader reader)
{
reader.ReadStartElement("TestClass");
this.ID=reader.ReadElementContentAsInt("ID", "");
this.CDataContent=reader.ReadElementContentAsString("Content", "");
reader.ReadEndElement();
}
void IXmlSerializable.WriteXml(XmlWriter writer)
{
writer.WriteStartElement("ID");
writer.WriteValue(this.ID);
writer.WriteEndElement();
writer.WriteStartElement("Content");
writer.WriteCData(this.CDataContent);
writer.WriteEndElement();
}
}
请留意ReadXml与WriteXml两个方法。一个将Xml的值读取出来赋值给当前实例,一个将当前实例的属性值写入到XML;而另外一个GetSchema在返回此对象对应的XML架构用于验证是否为合法的XML文档。
经过测试,上述方法可以达到第一种方法的效果,而且更加的安全,只不过在实现接口的时候需要麻烦一点。
对于一些无法直接序列化的类比如泛型的List等,也可以按照这种方式实现自定义的序列化与反序列化。
XmlSerializer类。不过在一些特殊情况下,CDATA类型的序列化与反序列化并不那么容易,或者说会出现一定的问题,本文将对此进行探讨。
1,新建测试项目和窗体
窗体代码如下:
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerializerTest
{
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
private void buttonSerialize_Click(object sender, EventArgs e)
{
var tc = new TestClass();
tc.ID = 2011;
tc.CDataContent = @"<table id=""test"">test";
var serializer = new XmlSerializer(tc.GetType());
var text = new StringBuilder();
using (var s = new StringWriter(text))
{
serializer.Serialize(s, tc);
}
this.textBoxXml.Text = text.ToString();
}
private void buttonDeserialize_Click(object sender, EventArgs e)
{
var serializer = new XmlSerializer(typeof(TestClass));
using (var s = new StringReader(this.textBoxXml.Text))
{
var tc = serializer.Deserialize(s) as TestClass;
if (tc != null)
{
MessageBox.Show(tc.CDataContent);
}
}
}
/// <summary>
/// Test class
/// </summary>
[Serializable]
public class TestClass
{
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Content")]
public string CDataContent { get; set; }
}
}
}
运行,点击Serialize按钮,可以得到序列化生成的XML文档:
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>2011</ID>
<Content><table id="test">test</Content>
</TestClass>
点击Deserialize按钮,可以得到以下结果:
---------------------------
---------------------------
<table id="test">test
---------------------------
OK
---------------------------
2,序列化为CDATA
如果需要将序列化生成的XML转化为以下格式(在实际中往往我们需要的是这种效果,而不是被转义的字符):
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>2011</ID>
<Content>
<![CDATA[
<table id="test">test]]>
</Content>
</TestClass>
这个时候我们至少有两种方法来实现。
2.1,修改实体类
我们将实体类TestClass修改为以下(关于为什么需要这样定义,请大家自行思考):
/// <summary>
/// Test class
/// </summary>
[Serializable]
public class TestClass
{
[XmlElement("ID")]
public int ID { get; set; }
[XmlIgnore]
public string CDataContent { get; set; }
[XmlElement("Content")]
public XmlNode[] Nodes
{
get
{
var dom = new XmlDocument();
return new XmlNode[] { dom.CreateCDataSection(this.CDataContent) };
}
set
{
if (value == null)
{
this.CDataContent = null;
return;
}
if (value.Length != 1)
throw new InvalidOperationException("Invalid array.");
var content = value[0];
if (null == content)
throw new InvalidOperationException("Node is null.");
this.CDataContent = content.Value;
}
}
}
运行后,TextBox的内容为:
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>2011</ID>
<Content><![CDATA[<table id="test">test]]></Content>
</TestClass>
已经实现。
2.2,实现IXmlSerializable接口
/// <summary>
/// Test class
/// </summary>
[Serializable]
public class TestClass : IXmlSerializable
{
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Content")]
public string CDataContent { get; set; }
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(XmlReader reader)
{
reader.ReadStartElement("TestClass");
this.ID=reader.ReadElementContentAsInt("ID", "");
this.CDataContent=reader.ReadElementContentAsString("Content", "");
reader.ReadEndElement();
}
void IXmlSerializable.WriteXml(XmlWriter writer)
{
writer.WriteStartElement("ID");
writer.WriteValue(this.ID);
writer.WriteEndElement();
writer.WriteStartElement("Content");
writer.WriteCData(this.CDataContent);
writer.WriteEndElement();
}
}
请留意ReadXml与WriteXml两个方法。一个将Xml的值读取出来赋值给当前实例,一个将当前实例的属性值写入到XML;而另外一个GetSchema在返回此对象对应的XML架构用于验证是否为合法的XML文档。
经过测试,上述方法可以达到第一种方法的效果,而且更加的安全,只不过在实现接口的时候需要麻烦一点。
对于一些无法直接序列化的类比如泛型的List等,也可以按照这种方式实现自定义的序列化与反序列化。
相关文章推荐
- XML 与 JSON 优劣对比
- As3.0 xml + Loader应用代码
- 网马生成器 MS Internet Explorer XML Parsing Buffer Overflow Exploit (vista) 0day
- ext读取两种结构的xml的代码
- C#针对xml基本操作及保存配置文件应用实例
- asp下查询xml的实现代码
- sqlserver FOR XML PATH 语句的应用
- 使用sp_xml_preparedocument处理XML文档的方法
- EBS xml publisher中文乱码问题及解决办法
- C#中的Linq to Xml详解
- C#操作XML文件实例汇总
- SQL Server中的XML数据进行insert、update、delete
- SQL Server中的XML数据进行insert、update、delete操作实现代码
- 关于SQLServer2005的学习笔记 XML的处理
- C#通过DataSet读写xml文件的方法
- C#实现基于XML配置MenuStrip菜单的方法
- php xml 入门学习资料
- Zend 输出产生XML解析错误
- PHP遍历XML文档所有节点的方法