更新:2007 年 11 月
將物件序列化成為 XML 文件,以及從 XML 文件將物件還原序列化。XmlSerializer 可讓您控制如何將物件編碼為 XML。
命名空間:
System.Xml.Serialization 組件:
System.Xml (在 System.Xml.dll 中)
Public Class XmlSerializer
Dim instance As XmlSerializer
public class XmlSerializer
public ref class XmlSerializer
public class XmlSerializer
public class XmlSerializer
XML 序列化 (Serialization) 是將物件公用屬性和欄位轉換為儲存或傳輸所用的序列格式 (此處即為 XML) 的程。還原序列化 (Deserialization) 是從 XML 輸出將物件重新建立成它的原始狀態。您可以將序列化視為在資料流或緩衝區中儲存物件狀態的方式。例如,ASP.NET 是使用 XmlSerializer 類別來編碼 XML Web Service 訊息。
您物件中的資料是用程式語言來描述的,該程式語言會建構如類別、欄位、屬性、基本型別 (Primitive Type)、陣列,甚至是以 XmlElement 或 XmlAttribute 物件為格式的內嵌 XML。您可以選擇以屬性註解建立自己的類別,或使用 XML 結構描述定義工具 (Xsd.exe) 來產生依據現有 XML 結構描述定義 (XSD) 文件的類別。如果有 XML 結構描述,您可以執行 Xsd.exe 來產生類別集,這些類別集是結構描述的強型別 (Strongly Typed),而且在序列化時以屬性註解來符合結構描述。
為了在物件之間傳輸資料,XML 需要從程式語言建構至 XML 結構描述的對應,以及從 XML 結構描述至程式語言建構的對應。XmlSerializer 和相關工具 (如 Xsd.exe),在設計階段和執行階段都提供了連接這兩項技術的橋樑。在設計階段,請使用 Xsd.exe 從自訂類別產生 XML 結構描述文件 (.xsd),或從指定的結構描述產生類別。不論哪一種情況,類別都會加註自訂屬性,指示 XmlSerializer 如何在 XML 結構描述系統和 Common Language Runtime 之間對應。在執行階段,可以將類別的執行個體序列化成符合指定之結構描述的 XML 文件。同樣地,這些 XML 文件可以還原序列化成執行階段物件。請注意,XML 結構描述是選擇性的,在設計階段或執行階段並不需要。
控制產生的 XML
若要控制產生的 XML,您可以將一些特別的屬性套用至類別和成員。例如,若要指定不同的 XML 項目名稱,可將 XmlElementAttribute 套用至公用欄位或屬性,並且設定 ElementName 屬性。如需類似屬性的完整清單,請參閱 控制 XML 序列化的屬性。您也可以實作 IXmlSerializable 介面,以控制 XML 輸出。
如果產生的 XML 必須符合全球資訊網協會 (www.w3.org) 文件<Simple Object Access Protocol (SOAP) 1.1>的第 5 節,您必須使用 XmlTypeMapping 來建構 XmlSerializer。若要進一步控制編碼的 SOAP XML,請使用 控制編碼 SOAP 序列化的屬性 中所列的屬性。
使用 XmlSerializer,您可以利用強型別類別來運作,而且還保有 XML 的彈性。在強型別類別中使用 XmlElement、XmlAttribute 或 XmlNode 型別的欄位或屬性,可以直接將 XML 文件的部分讀取至 XML 物件中。
如果使用可延伸 XML 結構描述,您也可以使用 XmlAnyElementAttribute 和 XmlAnyAttributeAttribute 屬性來序列化和還原序列化原始結構描述中找不到的項目和屬性。若要使用該物件,請將 XmlAnyElementAttribute 套用到傳回 XmlElement 物件陣列的欄位,或將 XmlAnyAttributeAttribute 套用到傳回 XmlAttribute 物件陣列的欄位。
如果屬性或欄位傳回複雜物件 (例如陣列或類別執行個體),XmlSerializer 會將它轉換為主要 XML 文件中的巢狀項目。例如,下列程式碼中的第一個類別,會傳回第二個類別的執行個體。
Public Class MyClass
Public MyObjectProperty As MyObject
End Class
Public Class MyObject
Public ObjectName As String
End Class
public class MyClass
{
public MyObject MyObjectProperty;
}
public class MyObject
{
public string ObjectName;
}
已序列化的 XML 輸出看起來會像這樣:
<MyClass>
<MyObjectProperty>
<ObjectName>My String</ObjectName>
</MyObjectProperty>
</MyClass>
如果結構描述包含選擇性的項目 (minOccurs = '0'),或如果結構描述包含預設值,您就有兩種選擇。一個選項是使用 System.ComponentModel..::.DefaultValueAttribute,指定預設值,如下列程式碼所示。
Public Class PurchaseOrder
<System.ComponentModel.DefaultValueAttribute ("2002")> _
Public Year As String
End Class
public class PurchaseOrder
{
[System.ComponentModel.DefaultValueAttribute ("2002")]
public string Year;
}
另一種選擇是使用特別的模式以建立 XmlSerializer 可辨識的布林 (Boolean) 欄位,並套用 XmlIgnoreAttribute 至該欄位。以 propertyNameSpecified 的格式建立其模式。例如,如果有名為 "MyFirstName" 的欄位,您也會建立名為 "MyFirstNameSpecified" 的欄位,指示 XmlSerializer 是否要產生名為 "MyFirstName" 的 XML 項目。這在下列範例中顯示。
Public Class OptionalOrder
' This field's value should not be serialized
' if it is uninitialized.
Public FirstOrder As String
' Use the XmlIgnoreAttribute to ignore the
' special field named "FirstOrderSpecified".
<System.Xml.Serialization.XmlIgnoreAttribute> _
Public FirstOrderSpecified As Boolean
End Class
public class OptionalOrder
{
// This field should not be serialized
// if it is uninitialized.
public string FirstOrder;
// Use the XmlIgnoreAttribute to ignore the
// special field named "FirstOrderSpecified".
[System.Xml.Serialization.XmlIgnoreAttribute]
public bool FirstOrderSpecified;
}
覆寫預設的序列化
動態產生的組件
為了增加效能,XML 序列化基礎結構會動態產生組件,以序列化和還原序列化指定的型別。基礎結構會尋找並重新使用那些組件。只有在使用下列建構函式時,才會出現這個行為:
XmlSerializer..::.XmlSerializer(Type)
XmlSerializer..::.XmlSerializer(Type, String)
如果您使用任何其他建構函式,則會產生相同組件的多個版本且無法卸載,導致記憶體遺漏和效能不佳。最簡單的解決方案就是使用先前提及的兩個建構函式。否則,您必須在 Hashtable 中快取組件,如下列範例所示。
Hashtable serializers = new Hashtable();
// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);
// Implement a method named GenerateKey that creates unique keys
// for each instance of the XmlSerializer. The code should take
// into account all parameters passed to the XmlSerializer
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);
// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null)
{
ser = new XmlSerializer(typeof(MyClass), myRoot);
// Cache the serializer.
serializers[key] = ser;
}
else
{
// Use the serializer to serialize, or deserialize.
}
Dim serializers As New Hashtable()
' Use the constructor that takes a type and XmlRootAttribute.
Dim s As New XmlSerializer(GetType([MyClass]), myRoot)
' Implement a method named GenerateKey that creates unique keys
' for each instance of the XmlSerializer. The code should take
' into account all parameters passed to the XmlSerializer
' constructor.
Dim key As Object = GenerateKey(GetType([MyClass]), myRoot)
' Check the local cache for a matching serializer.
Dim ser As XmlSerializer = CType(serializers(key), XmlSerializer)
If ser Is Nothing Then
ser = New XmlSerializer(GetType([MyClass]), myRoot)
' Cache the serializer.
serializers(key) = ser
Else
' Use the serializer to serialize, or deserialize.
End If
ArrayList 和泛型清單的序列化
XmlSerializer 無法序列化或還原序列化下列項目:
序列化 Unsigned Long 的列舉型別
如果下列條件成立,就無法產生 XmlSerializer 以序列化列舉型別:列舉型別為 Unsigned Long (C# 中為 ulong),而且列舉型別包含值大於 9,223,372,036,854,775,807 的任何成員。例如,下列項目無法序列化。
public enum LargeNumbers: ulong
{
a = 9223372036854775808
}
// At runtime, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));
以 Obsolete 屬性標示的物件不會再序列化
在 .NET Framework 3.5 中,XmlSerializer 類別不會再序列化標示為 [Obsolete] 的物件。
下列範例會含有名稱為 PurchaseOrder 及 Test 的兩個類別。該 PurchaseOrder 類別內含單次採購的相關資訊。Test 類別則包含了建立採購訂單以及讀取所建立之採購定單的方法。
Imports System
Imports System.Xml
Imports System.Xml.Serialization
Imports System.IO
Imports Microsoft.VisualBasic
' The XmlRootAttribute allows you to set an alternate name
' (PurchaseOrder) of the XML element, the element namespace; by
' default, the XmlSerializer uses the class name. The attribute
' also allows you to set the XML namespace for the element. Lastly,
' the attribute sets the IsNullable property, which specifies whether
' the xsi:null attribute appears if the class instance is set to
' a null reference.
<XmlRootAttribute("PurchaseOrder", _
Namespace := "http://www.cpandl.com", IsNullable := False)> _
Public Class PurchaseOrder
Public ShipTo As Address
Public OrderDate As String
' The XmlArrayAttribute changes the XML element name
' from the default of "OrderedItems" to "Items".
<XmlArrayAttribute("Items")> _
Public OrderedItems() As OrderedItem
Public SubTotal As Decimal
Public ShipCost As Decimal
Public TotalCost As Decimal
End Class 'PurchaseOrder
Public Class Address
' The XmlAttribute instructs the XmlSerializer to serialize the Name
' field as an XML attribute instead of an XML element (the default
' behavior).
<XmlAttribute()> _
Public Name As String
Public Line1 As String
' Setting the IsNullable property to false instructs the
' XmlSerializer that the XML attribute will not appear if
' the City field is set to a null reference.
<XmlElementAttribute(IsNullable := False)> _
Public City As String
Public State As String
Public Zip As String
End Class 'Address
Public Class OrderedItem
Public ItemName As String
Public Description As String
Public UnitPrice As Decimal
Public Quantity As Integer
Public LineTotal As Decimal
' Calculate is a custom method that calculates the price per item,
' and stores the value in a field.
Public Sub Calculate()
LineTotal = UnitPrice * Quantity
End Sub 'Calculate
End Class 'OrderedItem
Public Class Test
Public Shared Sub Main()
' Read and write purchase orders.
Dim t As New Test()
t.CreatePO("po.xml")
t.ReadPO("po.xml")
End Sub 'Main
Private Sub CreatePO(filename As String)
' Create an instance of the XmlSerializer class;
' specify the type of object to serialize.
Dim serializer As New XmlSerializer(GetType(PurchaseOrder))
Dim writer As New StreamWriter(filename)
Dim po As New PurchaseOrder()
' Create an address to ship and bill to.
Dim billAddress As New Address()
billAddress.Name = "Teresa Atkinson"
billAddress.Line1 = "1 Main St."
billAddress.City = "AnyTown"
billAddress.State = "WA"
billAddress.Zip = "00000"
' Set ShipTo and BillTo to the same addressee.
po.ShipTo = billAddress
po.OrderDate = System.DateTime.Now.ToLongDateString()
' Create an OrderedItem object.
Dim i1 As New OrderedItem()
i1.ItemName = "Widget S"
i1.Description = "Small widget"
i1.UnitPrice = CDec(5.23)
i1.Quantity = 3
i1.Calculate()
' Insert the item into the array.
Dim items(0) As OrderedItem
items(0) = i1
po.OrderedItems = items
' Calculate the total cost.
Dim subTotal As New Decimal()
Dim oi As OrderedItem
For Each oi In items
subTotal += oi.LineTotal
Next oi
po.SubTotal = subTotal
po.ShipCost = CDec(12.51)
po.TotalCost = po.SubTotal + po.ShipCost
' Serialize the purchase order, and close the TextWriter.
serializer.Serialize(writer, po)
writer.Close()
End Sub 'CreatePO
Protected Sub ReadPO(filename As String)
' Create an instance of the XmlSerializer class;
' specify the type of object to be deserialized.
Dim serializer As New XmlSerializer(GetType(PurchaseOrder))
' If the XML document has been altered with unknown
' nodes or attributes, handle them with the
' UnknownNode and UnknownAttribute events.
AddHandler serializer.UnknownNode, AddressOf serializer_UnknownNode
AddHandler serializer.UnknownAttribute, AddressOf serializer_UnknownAttribute
' A FileStream is needed to read the XML document.
Dim fs As New FileStream(filename, FileMode.Open)
' Declare an object variable of the type to be deserialized.
Dim po As PurchaseOrder
' Use the Deserialize method to restore the object's state with
' data from the XML document.
po = CType(serializer.Deserialize(fs), PurchaseOrder)
' Read the order date.
Console.WriteLine(("OrderDate: " & po.OrderDate))
' Read the shipping address.
Dim shipTo As Address = po.ShipTo
ReadAddress(shipTo, "Ship To:")
' Read the list of ordered items.
Dim items As OrderedItem() = po.OrderedItems
Console.WriteLine("Items to be shipped:")
Dim oi As OrderedItem
For Each oi In items
Console.WriteLine((ControlChars.Tab & oi.ItemName & ControlChars.Tab & _
oi.Description & ControlChars.Tab & oi.UnitPrice & ControlChars.Tab & _
oi.Quantity & ControlChars.Tab & oi.LineTotal))
Next oi
' Read the subtotal, shipping cost, and total cost.
Console.WriteLine(( New String(ControlChars.Tab, 5) & _
" Subtotal" & ControlChars.Tab & po.SubTotal))
Console.WriteLine(New String(ControlChars.Tab, 5) & _
" Shipping" & ControlChars.Tab & po.ShipCost )
Console.WriteLine( New String(ControlChars.Tab, 5) & _
" Total" & New String(ControlChars.Tab, 2) & po.TotalCost)
End Sub 'ReadPO
Protected Sub ReadAddress(a As Address, label As String)
' Read the fields of the Address object.
Console.WriteLine(label)
Console.WriteLine(ControlChars.Tab & a.Name)
Console.WriteLine(ControlChars.Tab & a.Line1)
Console.WriteLine(ControlChars.Tab & a.City)
Console.WriteLine(ControlChars.Tab & a.State)
Console.WriteLine(ControlChars.Tab & a.Zip)
Console.WriteLine()
End Sub 'ReadAddress
Private Sub serializer_UnknownNode(sender As Object, e As XmlNodeEventArgs)
Console.WriteLine(("Unknown Node:" & e.Name & ControlChars.Tab & e.Text))
End Sub 'serializer_UnknownNode
Private Sub serializer_UnknownAttribute(sender As Object, e As XmlAttributeEventArgs)
Dim attr As System.Xml.XmlAttribute = e.Attr
Console.WriteLine(("Unknown attribute " & attr.Name & "='" & attr.Value & "'"))
End Sub 'serializer_UnknownAttribute
End Class 'Test
using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
/* The XmlRootAttribute allows you to set an alternate name
(PurchaseOrder) of the XML element, the element namespace; by
default, the XmlSerializer uses the class name. The attribute
also allows you to set the XML namespace for the element. Lastly,
the attribute sets the IsNullable property, which specifies whether
the xsi:null attribute appears if the class instance is set to
a null reference. */
[XmlRootAttribute("PurchaseOrder", Namespace="http://www.cpandl.com",
IsNullable = false)]
public class PurchaseOrder
{
public Address ShipTo;
public string OrderDate;
/* The XmlArrayAttribute changes the XML element name
from the default of "OrderedItems" to "Items". */
[XmlArrayAttribute("Items")]
public OrderedItem[] OrderedItems;
public decimal SubTotal;
public decimal ShipCost;
public decimal TotalCost;
}
public class Address
{
/* The XmlAttribute instructs the XmlSerializer to serialize the Name
field as an XML attribute instead of an XML element (the default
behavior). */
[XmlAttribute]
public string Name;
public string Line1;
/* Setting the IsNullable property to false instructs the
XmlSerializer that the XML attribute will not appear if
the City field is set to a null reference. */
[XmlElementAttribute(IsNullable = false)]
public string City;
public string State;
public string Zip;
}
public class OrderedItem
{
public string ItemName;
public string Description;
public decimal UnitPrice;
public int Quantity;
public decimal LineTotal;
/* Calculate is a custom method that calculates the price per item,
and stores the value in a field. */
public void Calculate()
{
LineTotal = UnitPrice * Quantity;
}
}
public class Test
{
public static void Main()
{
// Read and write purchase orders.
Test t = new Test();
t.CreatePO("po.xml");
t.ReadPO("po.xml");
}
private void CreatePO(string filename)
{
// Create an instance of the XmlSerializer class;
// specify the type of object to serialize.
XmlSerializer serializer =
new XmlSerializer(typeof(PurchaseOrder));
TextWriter writer = new StreamWriter(filename);
PurchaseOrder po=new PurchaseOrder();
// Create an address to ship and bill to.
Address billAddress = new Address();
billAddress.Name = "Teresa Atkinson";
billAddress.Line1 = "1 Main St.";
billAddress.City = "AnyTown";
billAddress.State = "WA";
billAddress.Zip = "00000";
// Set ShipTo and BillTo to the same addressee.
po.ShipTo = billAddress;
po.OrderDate = System.DateTime.Now.ToLongDateString();
// Create an OrderedItem object.
OrderedItem i1 = new OrderedItem();
i1.ItemName = "Widget S";
i1.Description = "Small widget";
i1.UnitPrice = (decimal) 5.23;
i1.Quantity = 3;
i1.Calculate();
// Insert the item into the array.
OrderedItem [] items = {i1};
po.OrderedItems = items;
// Calculate the total cost.
decimal subTotal = new decimal();
foreach(OrderedItem oi in items)
{
subTotal += oi.LineTotal;
}
po.SubTotal = subTotal;
po.ShipCost = (decimal) 12.51;
po.TotalCost = po.SubTotal + po.ShipCost;
// Serialize the purchase order, and close the TextWriter.
serializer.Serialize(writer, po);
writer.Close();
}
protected void ReadPO(string filename)
{
// Create an instance of the XmlSerializer class;
// specify the type of object to be deserialized.
XmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder));
/* If the XML document has been altered with unknown
nodes or attributes, handle them with the
UnknownNode and UnknownAttribute events.*/
serializer.UnknownNode+= new
XmlNodeEventHandler(serializer_UnknownNode);
serializer.UnknownAttribute+= new
XmlAttributeEventHandler(serializer_UnknownAttribute);
// A FileStream is needed to read the XML document.
FileStream fs = new FileStream(filename, FileMode.Open);
// Declare an object variable of the type to be deserialized.
PurchaseOrder po;
/* Use the Deserialize method to restore the object's state with
data from the XML document. */
po = (PurchaseOrder) serializer.Deserialize(fs);
// Read the order date.
Console.WriteLine ("OrderDate: " + po.OrderDate);
// Read the shipping address.
Address shipTo = po.ShipTo;
ReadAddress(shipTo, "Ship To:");
// Read the list of ordered items.
OrderedItem [] items = po.OrderedItems;
Console.WriteLine("Items to be shipped:");
foreach(OrderedItem oi in items)
{
Console.WriteLine("\t"+
oi.ItemName + "\t" +
oi.Description + "\t" +
oi.UnitPrice + "\t" +
oi.Quantity + "\t" +
oi.LineTotal);
}
// Read the subtotal, shipping cost, and total cost.
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)
{
// Read the fields of the Address object.
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)
{
System.Xml.XmlAttribute attr = e.Attr;
Console.WriteLine("Unknown attribute " +
attr.Name + "='" + attr.Value + "'");
}
}
#using <System.Xml.dll>
#using <System.dll>
using namespace System;
using namespace System::Xml;
using namespace System::Xml::Serialization;
using namespace System::IO;
ref class Address;
ref class OrderedItem;
/* The XmlRootAttribute allows you to set an alternate name
(PurchaseOrder) of the XML element, the element namespace; by
default, the XmlSerializer uses the class name. The attribute
also allows you to set the XML namespace for the element. Lastly,
the attribute sets the IsNullable property, which specifies whether
the xsi:null attribute appears if the class instance is set to
a null reference. */
[XmlRootAttribute("PurchaseOrder",Namespace="http://www.cpandl.com",
IsNullable=false)]
public ref class PurchaseOrder
{
public:
Address^ ShipTo;
String^ OrderDate;
/* The XmlArrayAttribute changes the XML element name
from the default of "OrderedItems" to "Items". */
[XmlArrayAttribute("Items")]
array<OrderedItem^>^OrderedItems;
Decimal SubTotal;
Decimal ShipCost;
Decimal TotalCost;
};
public ref class Address
{
public:
/* The XmlAttribute instructs the XmlSerializer to serialize the Name
field as an XML attribute instead of an XML element (the default
behavior). */
[XmlAttributeAttribute]
String^ Name;
String^ Line1;
/* Setting the IsNullable property to false instructs the
XmlSerializer that the XML attribute will not appear if
the City field is set to a null reference. */
[XmlElementAttribute(IsNullable=false)]
String^ City;
String^ State;
String^ Zip;
};
public ref class OrderedItem
{
public:
String^ ItemName;
String^ Description;
Decimal UnitPrice;
int Quantity;
Decimal LineTotal;
/* Calculate is a custom method that calculates the price per item,
and stores the value in a field. */
void Calculate()
{
LineTotal = UnitPrice * Quantity;
}
};
public ref class Test
{
public:
static void main()
{
// Read and write purchase orders.
Test^ t = gcnew Test;
t->CreatePO( "po.xml" );
t->ReadPO( "po.xml" );
}
private:
void CreatePO( String^ filename )
{
// Create an instance of the XmlSerializer class;
// specify the type of object to serialize.
XmlSerializer^ serializer = gcnew XmlSerializer( PurchaseOrder::typeid );
TextWriter^ writer = gcnew StreamWriter( filename );
PurchaseOrder^ po = gcnew PurchaseOrder;
// Create an address to ship and bill to.
Address^ billAddress = gcnew Address;
billAddress->Name = "Teresa Atkinson";
billAddress->Line1 = "1 Main St.";
billAddress->City = "AnyTown";
billAddress->State = "WA";
billAddress->Zip = "00000";
// Set ShipTo and BillTo to the same addressee.
po->ShipTo = billAddress;
po->OrderDate = System::DateTime::Now.ToLongDateString();
// Create an OrderedItem object.
OrderedItem^ i1 = gcnew OrderedItem;
i1->ItemName = "Widget S";
i1->Description = "Small widget";
i1->UnitPrice = (Decimal)5.23;
i1->Quantity = 3;
i1->Calculate();
// Insert the item into the array.
array<OrderedItem^>^items = {i1};
po->OrderedItems = items;
// Calculate the total cost.
Decimal subTotal = Decimal(0);
System::Collections::IEnumerator^ myEnum = items->GetEnumerator();
while ( myEnum->MoveNext() )
{
OrderedItem^ oi = safe_cast<OrderedItem^>(myEnum->Current);
subTotal = subTotal + oi->LineTotal;
}
po->SubTotal = subTotal;
po->ShipCost = (Decimal)12.51;
po->TotalCost = po->SubTotal + po->ShipCost;
// Serialize the purchase order, and close the TextWriter.
serializer->Serialize( writer, po );
writer->Close();
}
protected:
void ReadPO( String^ filename )
{
// Create an instance of the XmlSerializer class;
// specify the type of object to be deserialized.
XmlSerializer^ serializer = gcnew XmlSerializer( PurchaseOrder::typeid );
/* If the XML document has been altered with unknown
nodes or attributes, handle them with the
UnknownNode and UnknownAttribute events.*/
serializer->UnknownNode += gcnew XmlNodeEventHandler( this, &Test::serializer_UnknownNode );
serializer->UnknownAttribute += gcnew XmlAttributeEventHandler( this, &Test::serializer_UnknownAttribute );
// A FileStream is needed to read the XML document.
FileStream^ fs = gcnew FileStream( filename,FileMode::Open );
// Declare an object variable of the type to be deserialized.
PurchaseOrder^ po;
/* Use the Deserialize method to restore the object's state with
data from the XML document. */
po = dynamic_cast<PurchaseOrder^>(serializer->Deserialize( fs ));
// Read the order date.
Console::WriteLine( "OrderDate: {0}", po->OrderDate );
// Read the shipping address.
Address^ shipTo = po->ShipTo;
ReadAddress( shipTo, "Ship To:" );
// Read the list of ordered items.
array<OrderedItem^>^items = po->OrderedItems;
Console::WriteLine( "Items to be shipped:" );
System::Collections::IEnumerator^ myEnum1 = items->GetEnumerator();
while ( myEnum1->MoveNext() )
{
OrderedItem^ oi = safe_cast<OrderedItem^>(myEnum1->Current);
Console::WriteLine( "\t{0}\t{1}\t{2}\t{3}\t{4}", oi->ItemName, oi->Description, oi->UnitPrice, oi->Quantity, oi->LineTotal );
}
Console::WriteLine( "\t\t\t\t\t Subtotal\t{0}", po->SubTotal );
Console::WriteLine( "\t\t\t\t\t Shipping\t{0}", po->ShipCost );
Console::WriteLine( "\t\t\t\t\t Total\t\t{0}", po->TotalCost );
}
void ReadAddress( Address^ a, String^ label )
{
// Read the fields of the Address object.
Console::WriteLine( label );
Console::WriteLine( "\t{0}", a->Name );
Console::WriteLine( "\t{0}", a->Line1 );
Console::WriteLine( "\t{0}", a->City );
Console::WriteLine( "\t{0}", a->State );
Console::WriteLine( "\t{0}", a->Zip );
Console::WriteLine();
}
private:
void serializer_UnknownNode( Object^ /*sender*/, XmlNodeEventArgs^ e )
{
Console::WriteLine( "Unknown Node:{0}\t{1}", e->Name, e->Text );
}
void serializer_UnknownAttribute( Object^ /*sender*/, XmlAttributeEventArgs^ e )
{
System::Xml::XmlAttribute^ attr = e->Attr;
Console::WriteLine( "Unknown attribute {0}='{1}'", attr->Name, attr->Value );
}
};
int main()
{
Test::main();
}
import System.*;
import System.Xml.*;
import System.Xml.Serialization.*;
import System.IO.*;
/* The XmlRootAttribute allows you to set an alternate name
(PurchaseOrder) of the XML element, the element namespace; by
default, the XmlSerializer uses the class name. The attribute
also allows you to set the XML namespace for the element. Lastly,
the attribute sets the IsNullable property, which specifies whether
the xsi:null attribute appears if the class instance is set to
a null reference. */
/** @attribute XmlRootAttribute("PurchaseOrder",
Namespace = "http://www.cpandl.com", IsNullable = false)
*/
public class PurchaseOrder
{
public Address shipTo;
public String orderDate;
/* The XmlArrayAttribute changes the XML element name
from the default of "OrderedItems" to "Items". */
/** @attribute XmlArrayAttribute("Items")
*/
public OrderedItem orderedItems[];
public System.Decimal subTotal;
public System.Decimal shipCost;
public System.Decimal totalCost;
} //PurchaseOrder
public class Address
{
/* The XmlAttribute instructs the XmlSerializer to serialize the Name
field as an XML attribute instead of an XML element (the default
behavior). */
/** @attribute XmlAttribute()
*/
public String name;
public String line1;
/* Setting the IsNullable property to false instructs the
XmlSerializer that the XML attribute will not appear if
the City field is set to a null reference. */
/** @attribute XmlElementAttribute(IsNullable = false)
*/
public String city;
public String state;
public String zip;
} //Address
public class OrderedItem
{
public String itemName;
public String description;
public System.Decimal unitPrice;
public int quantity;
public System.Decimal lineTotal;
/* Calculate is a custom method that calculates the price per item,
and stores the value in a field. */
public void Calculate()
{
lineTotal = Decimal.Multiply(unitPrice, Convert.ToDecimal(quantity));
} //Calculate
} //OrderedItem
public class Test
{
public static void main(String[] args)
{
// Read and write purchase orders.
Test t = new Test();
t.CreatePO("po.xml");
t.ReadPO("po.xml");
} //main
private void CreatePO(String fileName)
{
// Create an instance of the XmlSerializer class;
// specify the type of object to serialize.
XmlSerializer serializer =
new XmlSerializer(PurchaseOrder.class.ToType());
TextWriter writer = new StreamWriter(fileName);
PurchaseOrder po = new PurchaseOrder();
// Create an address to ship and bill to.
Address billAddress = new Address();
billAddress.name = "Teresa Atkinson";
billAddress.line1 = "1 Main St.";
billAddress.city = "AnyTown";
billAddress.state = "WA";
billAddress.zip = "00000";
// Set ShipTo and BillTo to the same addressee.
po.shipTo = billAddress;
po.orderDate = System.DateTime.get_Now().ToLongDateString();
// Create an OrderedItem object.
OrderedItem i1 = new OrderedItem();
i1.itemName = "Widget S";
i1.description = "Small widget";
i1.unitPrice = Convert.ToDecimal(5.23);
i1.quantity = 3;
i1.Calculate();
// Insert the item into the array.
OrderedItem items[] = { i1 };
po.orderedItems = items;
// Calculate the total cost.
System.Decimal subTotal = new System.Decimal();
for (int iCtr = 0; iCtr < items.length; iCtr++) {
OrderedItem oi = items[iCtr];
subTotal = Decimal.Add(subTotal, oi.lineTotal);
}
po.subTotal = subTotal;
po.shipCost = Convert.ToDecimal(12.51);
po.totalCost = Decimal.Add(po.subTotal, po.shipCost);
// Serialize the purchase order, and close the TextWriter.
serializer.Serialize(writer, po);
writer.Close();
} //CreatePO
protected void ReadPO(String fileName)
{
// Create an instance of the XmlSerializer class;
// specify the type of object to be deserialized.
XmlSerializer serializer =
new XmlSerializer(PurchaseOrder.class.ToType());
/* If the XML document has been altered with unknown
nodes or attributes, handle them with the
UnknownNode and UnknownAttribute events.*/
serializer.add_UnknownNode(
new XmlNodeEventHandler(Serializer_UnknownNode));
serializer.add_UnknownAttribute(
new XmlAttributeEventHandler(Serializer_UnknownAttribute));
// A FileStream is needed to read the XML document.
FileStream fs = new FileStream(fileName, FileMode.Open);
// Declare an object variable of the type to be deserialized.
PurchaseOrder po;
/* Use the Deserialize method to restore the object's state with
data from the XML document. */
po = (PurchaseOrder)serializer.Deserialize(fs);
// Read the order date.
Console.WriteLine("OrderDate: " + po.orderDate);
// Read the shipping address.
Address shipTo = po.shipTo;
ReadAddress(shipTo, "Ship To:");
// Read the list of ordered items.
OrderedItem items[] = po.orderedItems;
Console.WriteLine("Items to be shipped:");
for (int iCtr = 0; iCtr < items.length; iCtr++) {
OrderedItem oi = items[iCtr];
Console.WriteLine("\t" + oi.itemName + "\t"
+ oi.description + "\t" + oi.unitPrice + "\t"
+ oi.quantity + "\t" + oi.lineTotal);
}
// Read the subtotal, shipping cost, and total cost.
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);
} //ReadPO
protected void ReadAddress(Address a, String label)
{
// Read the fields of the Address object.
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();
} //ReadAddress
private void Serializer_UnknownNode(Object sender, XmlNodeEventArgs e)
{
Console.WriteLine("Unknown Node:" + e.get_Name() + "\t" + e.get_Text());
} //Serializer_UnknownNode
private void Serializer_UnknownAttribute(Object sender,
XmlAttributeEventArgs e)
{
System.Xml.XmlAttribute attr = e.get_Attr();
Console.WriteLine("Unknown attribute " + attr.get_Name() + "='"
+ attr.get_Value() + "'");
} //Serializer_UnknownAttribute
} //Test
System..::.Object
System.Xml.Serialization..::.XmlSerializer
此型別具備執行緒安全。
Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile for Smartphone, Windows Mobile for Pocket PC, Xbox 360
.NET Framework 和 .NET Compact Framework 並不支援各種平台的所有版本。如需支援平台版本的相關資訊,請參閱.NET Framework 系統需求。
.NET Framework
支援版本:3.5、3.0、2.0、1.1、1.0
.NET Compact Framework
支援版本:3.5、2.0
XNA Framework
支援版本:2.0、1.0
參考
XmlSerializer
其他資源