XmlSerializer 序列化与反序列化CDATA 以及实现

本文探讨了如何使用XmlSerializer类进行对象状态的序列化与反序列化,并详细介绍了处理CDATA类型的序列化问题的方法。通过修改实体类或实现IXmlSerializable接口,可以实现在序列化时保留原始CDATA内容,避免被转义。此外,文章还展示了如何对无法直接序列化的类如泛型List等进行自定义序列化与反序列化的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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>&lt;table id="test"&gt;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等,也可以按照这种方式实现自定义的序列化与反序列化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值