XML序列化
时间:2010-09-28 来源:czyhsl
序列化是将对象转化成易于传输的形式的过程。例如:可以序列化对象,并使用HTTP通过Internet在客户端和服务器之间进行传输。另一方面,反序列化在流中重新构造对象。
XML序列化只将对象的公共字段和属性值序列化为XML流。它不能转换方法、索引器、私有字段或只读属性(只读集合除外)。若要序列化对象的所有公共和私有字段和属性,需要使用DataContractSerializer而不要使用XML序列化。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Runtime.Serialization;
using System.Xml;
using System.IO;
namespace DataContractSerializerDemo
{
[DataContract(Name = "Customer", Namespace = "http://www.contoso.com")]
class Person
{
[DataMember()]
public string FirstName;
[DataMember]
public string LastName;
[DataMember()]
public int ID;
public Person(string newfName, string newlName, int newID)
{
FirstName = newfName;
LastName = newlName;
ID = newID;
}
private ExtensionDataObject extensionData_Value;
public ExtensionDataObject ExtensionData
{
get
{
return extensionData_Value;
}
set
{
extensionData_Value = value;
}
}
}
class Test
{
private Test() { }
static void Main(string[] args)
{
try
{
WriteObject("DataContractSerializerDemo.xml");
ReadOjbect("DataContractSerializerDemo.xml");
}
catch (SerializationException serExc)
{
Console.WriteLine("Serialization Failed");
Console.WriteLine(serExc.Message);
}
catch(Exception exc)
{
Console.WriteLine(
"The serialization operation failed: {0} StackTrace: {1}",
exc.Message, exc.StackTrace);
}
finally
{
Console.WriteLine("Press <Enter> to exit....");
Console.ReadLine();
}
}
public static void WriteObject(string fileName)
{
Console.WriteLine("Creating a Person object and serializing it.");
Person p1 = new Person("Zighetti", "Barbara", 101);
FileStream write = new FileStream(fileName, FileMode.Create);
DataContractSerializer ser = new DataContractSerializer(typeof(Person));
ser.WriteObject(write, p1);
write.Close();
}
public static void ReadOjbect(string fileName)
{
Console.WriteLine("Deserializing an instance of the object.");
FileStream fs = new FileStream(fileName, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(Person));
Person deserializedPerson = (Person)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
Console.WriteLine(String.Format("{0} {1}, ID: {2}",
deserializedPerson.FirstName, deserializedPerson.LastName,
deserializedPerson.ID));
}
}
}
这是DataContractSerializer的一个Demo,必须要在Person类上指定或实现一个数据协定,当用于类成员时,指定该成员是数据协定的一部分。
谈到XML序列化,就不得不提XmlSerializer类,它的主要用途就是将对象序列化到文档中和从XML文档中反序列化对象。XML可序列化的项包含以下:
1)公共类的读/写属性和字段
2)实现ICollection或IEnumerable的类
3)XmlElement对象
4)XmlNode对象
5)DataSet对象
序列化数据集
代码using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Data;
namespace XmlSerializerDemo
{
class Test
{
static void Main(string[] args)
{
SerializeDataSet(@"D:\Dataset.xml");
}
private static void SerializeDataSet(string filename)
{
XmlSerializer ser = new XmlSerializer(typeof(DataSet));
DataSet ds = new DataSet("myDataSet");
DataTable t = new DataTable("table1");
DataColumn c = new DataColumn("thing");
t.Columns.Add(c);
ds.Tables.Add(t);
DataRow r;
for (int i = 0; i < 10; i++)
{
r = t.NewRow();
r[0] = "Thing " + i;
t.Rows.Add(r);
}
TextWriter writer = new StreamWriter(filename);
ser.Serialize(writer, ds);
writer.Close();
}
}
}
序列化XmlElement和XmlNode
代码using System;输出
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
namespace XmlSerializerDemo
{
class Test
{
static void Main(string[] args)
{
SerializeElement(@"D:\Dataset.xml");
}
private static void SerializeElement(string filename)
{
XmlSerializer ser = new XmlSerializer(typeof(XmlElement));
XmlElement myElement =
new XmlDocument().CreateElement("MyElement", "ns");
myElement.InnerText = "Hello World";
TextWriter writer = new StreamWriter(filename);
ser.Serialize(writer, myElement);
writer.Close();
}
private static void SerializeNode(string filename)
{
XmlSerializer ser = new XmlSerializer(typeof(XmlNode));
XmlNode myNode = new XmlDocument().
CreateNode(XmlNodeType.Element, "MyNode", "ns");
myNode.InnerText = "Hello Node";
TextWriter writer = new StreamWriter(filename);
ser.Serialize(writer, myNode);
writer.Close();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<MyElement xmlns="ns">Hello World</MyElement>
序列化复杂对象
代码using System;输出 代码
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
namespace XmlSerializerDemo
{
class Test
{
static void Main(string[] args)
{
SerailizeClass(@"D:\SerialClass.xml");
}
private static void SerailizeClass(string filename)
{
XmlSerializer serializer =
new XmlSerializer(typeof(PurchaseOrder));
TextWriter write = new StreamWriter(filename);
PurchaseOrder po = new PurchaseOrder();
Address addr = new Address();
addr.FirstName = "Beijing";
po.MyAddress = addr;
serializer.Serialize(write, po);
write.Close();
}
}
public class PurchaseOrder
{
public Address MyAddress;
}
public class Address
{
public string FirstName;
}
}
<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyAddress>
<FirstName>Beijing</FirstName>
</MyAddress>
</PurchaseOrder>
序列化对象数组
代码using System;输出
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
namespace XmlSerializerDemo
{
class Test
{
static void Main(string[] args)
{
SerializeClassArray(@"D:\Dataset.xml");
}
private static void SerializeClassArray(string filename)
{
XmlSerializer serializer =
new XmlSerializer(typeof(PurchaseOrder));
TextWriter write = new StreamWriter(filename);
PurchaseOrder po = new PurchaseOrder();
Item item = new Item();
item.ItemID = "xz01";
item.ItemPrice = (decimal)3.2;
Item item1 = new Item();
item1.ItemID = "xz02";
item1.ItemPrice = (decimal)4.5;
Item[] items = { item, item1};
po.ItemsOrders = items;
serializer.Serialize(write, po);
write.Close();
}
}
public class PurchaseOrder
{
public Item[] ItemsOrders;
}
public class Item
{
public string ItemID;
public decimal ItemPrice;
}
}
代码
<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ItemsOrders>
<Item>
<ItemID>xz01</ItemID>
<ItemPrice>3.2</ItemPrice>
</Item>
<Item>
<ItemID>xz02</ItemID>
<ItemPrice>4.5</ItemPrice>
</Item>
</ItemsOrders>
</PurchaseOrder>
序列化实现ICollection的类
代码using System;输出
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Collections;
using System.Xml;
namespace XmlSerializerDemo
{
class Test
{
static void Main(string[] args)
{
SerializeCollection(@"D:\SerialCollection.xml");
}
private static void SerializeCollection(string filename)
{
Employees Emps = new Employees();
Emps.CollectionName = "Employees";
Employee emp = new Employee("Yao", "1111");
Emps.Add(emp);
XmlSerializer serializer = new XmlSerializer(typeof(Employees));
TextWriter write = new StreamWriter(filename);
serializer.Serialize(write, Emps);
write.Close();
}
}
public class Employee
{
public string EmpName;
public string EmpID;
public Employee() { }
public Employee(string empName, string empID)
{
EmpName = empName;
EmpID = empID;
}
}
public class Employees : ICollection
{
public string CollectionName;
public ArrayList empArray = new ArrayList();
public Employee this[int index]
{
get { return (Employee)empArray[index]; }
}
#region ICollection 成员
public void CopyTo(Array array, int index)
{
empArray.CopyTo(array, index);
}
public int Count
{
get { return empArray.Count; }
}
public bool IsSynchronized
{
get { return false; }
}
public object SyncRoot
{
get { return this; }
}
#endregion
#region IEnumerable 成员
public IEnumerator GetEnumerator()
{
return empArray.GetEnumerator();
}
#endregion
public void Add(Employee newEmployee)
{
empArray.Add(newEmployee);
}
}
}
代码
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfEmployee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Employee>
<EmpName>Yao</EmpName>
<EmpID>1111</EmpID>
</Employee>
</ArrayOfEmployee>
下面这是一个综合到前面所讲到所有的序列化的示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Collections;
using System.Xml;
namespace XmlSerializerDemo
{
class Test
{
static void Main(string[] args)
{
Test t = new Test();
t.CreatePO("po.xml");
t.ReadPO("po.xml");
}
private void CreatePO(string filename)
{
XmlSerializer serializer =
new XmlSerializer(typeof(PurchaseOrder));
TextWriter write = new StreamWriter(filename);
PurchaseOrder po = new PurchaseOrder();
Address address = new Address();
address.Name = "Teresa Atkinson";
address.Line1 = "1 Main St.";
address.City = "AnyTown";
address.State = "WA";
address.Zip = "00000";
po.ShipTo = address;
po.OrderDate = DateTime.Now.ToLongDateString();
OrderItem ol = new OrderItem();
ol.ItemName = "Widget S";
ol.Description = "Small widget";
ol.UnitPrice = (decimal)5.23;
ol.Quantity = 3;
ol.Calculate();
OrderItem[] items = { ol };
po.OrderItems = items;
decimal subTotal = new decimal();
foreach (OrderItem oi in items)
{
subTotal += oi.LineTotal;
}
po.SubTotal = subTotal;
po.ShipCost = (decimal)12.51;
po.TotalCost = po.SubTotal + po.ShipCost;
serializer.Serialize(write, po);
write.Close();
}
protected void ReadPO(string filename)
{
XmlSerializer serializer =
new XmlSerializer(typeof(PurchaseOrder));
serializer.UnknownNode += new
XmlNodeEventHandler(serializer_UnknownNode);
serializer.UnknownAttribute += new
XmlAttributeEventHandler(serializer_UnknownAttribute);
FileStream fs = new FileStream(filename, FileMode.Open);
PurchaseOrder po;
po = (PurchaseOrder)serializer.Deserialize(fs);
Console.WriteLine("OrderDate: " + po.OrderDate);
Address shipTo = po.ShipTo;
ReadAddress(shipTo, "Ship To:");
OrderItem[] items = po.OrderItems;
Console.WriteLine("Items to be shipped:");
foreach (OrderItem oi in items)
{
Console.WriteLine("\t" +
oi.ItemName + "\t" +
oi.Description + "\t" +
oi.UnitPrice + "\t" +
oi.Quantity + "\t" +
oi.LineTotal);
}
Console.WriteLine("\t\t\t\t\t Subtotal\t" + po.SubTotal);
Console.WriteLine("\t\t\t\t\t Shipping\t" + po.ShipCost);
Console.WriteLine("\t\t\t\t\t Total\t\t" + po.TotalCost);
}
protected void ReadAddress(Address a, string label)
{
Console.WriteLine(label);
Console.WriteLine("\t" + a.Name);
Console.WriteLine("\t" + a.Line1);
Console.WriteLine("\t" + a.City);
Console.WriteLine("\t" + a.State);
Console.WriteLine("\t" + a.Zip);
Console.WriteLine();
}
private void serializer_UnknownNode(object sender, XmlNodeEventArgs e)
{
Console.WriteLine("Unknown Node:" + e.Name + "\t" + e.Text);
}
private void serializer_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
XmlAttribute attr = e.Attr;
Console.WriteLine("Unknown attribute " +
attr.Name + "='" + attr.Value + "'");
}
}
[XmlRootAttribute("PurchaseOrder",
IsNullable = false)]
public class PurchaseOrder
{
public Address ShipTo;
public string OrderDate;
[XmlArrayAttribute("Items")]
public OrderItem[] OrderItems;
public decimal SubTotal;
public decimal ShipCost;
public decimal TotalCost;
}
public class Address
{
[XmlAttribute]
public string Name;
public string Line1;
[XmlElementAttribute(IsNullable = false)]
public string City;
public string State;
public string Zip;
}
public class OrderItem
{
public string ItemName;
public string Description;
public decimal UnitPrice;
public int Quantity;
public decimal LineTotal;
public void Calculate()
{
LineTotal = UnitPrice * Quantity;
}
}
}
最后附带上使用XmlSerializer类时,应该注意的一些事项:
1)序列化数据只包含数据本身和类的结构。类型标识和程序集信息不包括在内。
2)只能序列化公共属性和字段。属性必须具有公共访问器(get和set方法)。如果必须序列化非公共数据,使用DataContractSerializer类而不使用XML序列化。
3)类必须具有默认的构造函数才能被XmlSerailizer序列化。
4)方法不能被序列化。
5)如果可实现 IEnumerable 或 ICollection 的类满足特定要求。实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。Add 方法的参数必须与从 IEnumerator.Current 属性返回的类型一致(多态),该属性是从 GetEnumerator 方法返回的。实现 ICollection(如 CollectionBase)的类还必须有一个采用整数的公共 Item 索引属性(在 C# 中为索引器),而且必须有一个 integer 类型的公共 Count 属性。传递给 Add 方法的参数的类型必须与从 Item 属性返回的类型相同,或者为此类型的基之一。