您的位置:首页 > 其它

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等,也可以按照这种方式实现自定义的序列化与反序列化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  xml