XML 序列化 【译】
原文连接:http://www.diranieh.com/NETSerialization/XMLSerialization.htm
总结:
- 介绍
- XML 序列化示例
- XML Schema 定义文档
- 通过 Attributes来控制XML 序列化
- 重写XML 序列化
- XML Namespace
- XML 序列化和XML Web Service
介绍
序列化是指把对象转化为可以持续存续或者跨流程/机器传输的过程。它的方向过程就是反序列化,就是把把序列化以后的文件转换为原始的对象。.NET 提供了两种序列化的技术:二进制和XML.
XML 序列化
XML 序列化可以序列化一个类的公有成员和属性 或者参数,返回XML 数据流。XML 序列化不会序列化 方法,索引,私有成员 或者只读属性(除了只读集合)。因为XML是一个公开标准,XML 数据流可以被任何平台的应用传输。例如: ASP.NET Web Service 用XML 序列化创建XML 数据流 从而通过网络来传输数据。相反的,反序列化用这种数据流来构建对象。
不相二进制序列化,XML 数列化不会保存类型,换句话说,它不会包含数据类型。比如:在公司命名空间里有一个员工对象,这个不能保证反序列化的对象有相同的类型。
用System.Xml.Serialization.Xmlserializer 来执行XML 序列化和反序列化。最重要的方法是Serialize 和 Deserialize。
创建类的时候,你可以直接用C#或者其他.NET语言代码来写一个类,或者用XML Schema Definition tool(xsd.exe)根据现有的XSD来生成类。 当一个来自XSD的类序列化了,把生成的XML 依附到XML Schema。你还可以选择用.NET Framework中的其他类 比如 XmlReader和XmlWriter, 这两个类可以用来解析任何XML 数据流。相反的,当你想要XML 数据流满足XML Schema 你就可以用XmlSerializer。
用XmlSerializer生成xml数据流的时候 你可以设置XML的命名空间,元素名,属性名.....XmlSerializer 类可以更进一步的数列化对象 生成 编码的SOAP Xml 数据流。需要注意的是,XmlSerializer 类可以生成SOAP消息和传到XML Web Service。
可序列化的项目:
以下的几点是可以被XmlSerializer序列化的:
- 公有 可读/可写的属性
- 公有成员
- 继承了ICollection 或 IEnumerable的类
- XmlElement 对象
- XmlNode 对象
- DataSet 对象
用XML 序列化的优势
用XmlSerialzer有比较完整的控制劝, 比如:
- 可以自定义成员或属性是作为元素还是属性
- 可以自定义XML的命名空间
- 假如成员/属性的名字不合适,可以自定义元素或者属性的名字
XML 序列化注意事项
以下是需要注意的地方:
- 不包含类型区别和assembly信息,如果要区分类别用二进制序列化
- 只有公有的属性和成员可以被序列化,需要序列化非公有数据请用二进制序列化
- 如果需要序列化一个类,那么这个类一定要有默认构造函数
- 方法不能被序列化
- XmlSerialzer可以序列化继承ICollection或者IEnumerable的类
例子
以下的例子展示额怎么序列化一个简单的类,需要注意的是类必须要有默认构造函数:
namespace XMLSerialization { [Serializable()] public class MyBasicClass { public string strPublic; public MyBasicClass( ) { strPublic = "hello"; } } }
// Serialization / Deserialization code uisng System.Xml.Serialization; ... private void btnXMLSerialization_Click(object sender, System.EventArgs e) { XMLSerializeMyBasicCObject(); XMLDeSerializeMyBasicCObject(); } private void XMLSerializeMyBasicCObject() { // Create a serializable instnace XMLSerialization.MyBasicClass ob = new XMLSerialization.MyBasicClass(); // Initialize a storage medium to hold the serialized object Stream stream = new FileStream( "BasicXMLSerializa.xml", FileMode.Create, FileAccess.Write, FileShare.Write); // Serialize an object into the storage medium referenced by 'stream' object. XmlSerializer xmlserializer = new XmlSerializer( typeof(XMLSerialization.MyBasicClass) ); xmlserializer.Serialize( stream, ob ); // Cleanup stream.Close(); } private void XMLDeSerializeMyBasicCObject() { // Read the file back into a stream Stream stream = new FileStream( "BasicXMLSerializa.xml", FileMode.Open, FileAccess.Read, FileShare.Read); // Now create a binary formatter XmlSerializer xmlserializer = new XmlSerializer( typeof(XMLSerialization.MyBasicClass) ); // Deserialize the object and use it XMLSerialization.MyBasicClass ob = (XMLSerialization.MyBasicClass)xmlserializer.Deserialize( stream ); Trace.WriteLine( ob.strPublic ); // Cleanup stream.Close(); }
结果如下:
<?xml version="1.0"?> <MyBasicClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <strPublic>hello</strPublic> </MyBasicClass>
DataSet 序列化
以下展示了怎么序列化DataSet:
private void btnDataSet_Click(object sender, System.EventArgs e) { // Construct a DataSet System.Data.DataSet ds = new DataSet( "MyDataSet" ); System.Data.DataTable dt = new DataTable( "MyDataTable" ); System.Data.DataColumn dc1 = new DataColumn( "ID", typeof (int) ); System.Data.DataColumn dc2 = new DataColumn( "Name", typeof (string) ); dt.Columns.Add( dc1 ); dt.Columns.Add( dc2 ); ds.Tables.Add( dt ); // Add some rows for (int i = 0; i < 5; i ++) { DataRow row = dt.NewRow(); row[0] = i; row[1] = i.ToString(); dt.Rows.Add ( row ); } // Now serialize the DataSet System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer( typeof( DataSet ) ); Stream stream = new FileStream( "DataSet.xml", FileMode.CreateNew); serializer.Serialize( stream, ds ); // Clean up stream.Close(); }
结果如下:
<?xml version="1.0"?> <DataSet> <xs:schema id="MyDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="MyDataSet" msdata:IsDataSet="true" msdata:Locale="en-GB"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="MyDataTable"> <xs:complexType> <xs:sequence> <xs:element name="ID" type="xs:int" minOccurs="0" /> <xs:element name="Name" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"> <MyDataSet> <MyDataTable diffgr:id="MyDataTable1" msdata:rowOrder="0" diffgr:hasChanges="inserted"> <ID>0</ID> <Name>0</Name> </MyDataTable> <MyDataTable diffgr:id="MyDataTable2" msdata:rowOrder="1" diffgr:hasChanges="inserted"> <ID>1</ID> <Name>1</Name> </MyDataTable> <MyDataTable diffgr:id="MyDataTable3" msdata:rowOrder="2" diffgr:hasChanges="inserted"> <ID>2</ID> <Name>2</Name> </MyDataTable> <MyDataTable diffgr:id="MyDataTable4" msdata:rowOrder="3" diffgr:hasChanges="inserted"> <ID>3</ID> <Name>3</Name> </MyDataTable> <MyDataTable diffgr:id="MyDataTable5" msdata:rowOrder="4" diffgr:hasChanges="inserted"> <ID>4</ID> <Name>4</Name> </MyDataTable> </MyDataSet> </diffgr:diffgram> </DataSet>
复杂对象序列化
假如类的属性或是成员返回复杂对象(array 或者实例,XmlSerializer会把它转化为嵌套在xml文件里的成员,如下:
// Classes used in serializing. An Order object contains 0 or more Item objects namespace XMLSerialization { [Serializable] public class Item { public string strProductName; public int nProductID; public Item() { strProductName = ""; nProductID = 0; } public Item( string s, int n ) { strProductName = s; nProductID = n; } } [Serializable] public class Order { // Must indicate what kind of elements exist in the ArrayList. See // Controlling XML Serialization Through Attributes [XmlElement( typeof(Item) )] public ArrayList alOrders; public Order() { alOrders = new ArrayList(); } [XmlInclude( typeof( Item) )] public void Add( Item i ) { alOrders.Add( i ); } } }
// The function creates an Order that contains many Items and then serializes the Order object private void btnComplexOb_Click(object sender, System.EventArgs e) { Stream stream = null; try { // Create an object that contains other objects XMLSerialization.Order order = new XMLSerialization.Order(); order.Add( new XMLSerialization.Item( "Apples", 10 ) ); order.Add( new XMLSerialization.Item( "Oranges", 20 ) ); order.Add( new XMLSerialization.Item( "Avocados", 30 ) ); // Now serialize the class System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer( typeof( XMLSerialization.Order ) ); stream = new FileStream( "ComplexObject.xml", FileMode.Create ); serializer.Serialize( stream, order ); stream.Close(); } catch( Exception ex ) { stream.Close(); Trace.WriteLine ( ex.Message ); } }
<?xml version="1.0"?> <Order xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <alOrders> <strProductName>Apples</strProductName> <nProductID>10</nProductID> </alOrders> <alOrders> <strProductName>Oranges</strProductName> <nProductID>20</nProductID> </alOrders> <alOrders> <strProductName>Avocados</strProductName> <nProductID>30</nProductID> </alOrders> </Order>