人們一直高喊XML是解決系統互聯問題的關鍵 而NET framework 也為處理XML數據提供了許多不同的類庫 XmlDocument 類能讓你像處理文件一樣處理XML 數據 而XmlReader XmlWriter 和它們的派生類使你能夠將XML 數據做為數據流處理 XmlSerializer 則提供了另外的方法 它使你能夠將自己的對象串行和反串行化為XML 串行化數據既能夠讓你像處理文件一樣對數據進行隨機存取 同時又能夠跳過你不感興趣的元素 在本文中 我將向你展示如何使用XmlSerializer類以及如何在你的類中添加屬性來控制串行化過程
XmlSerializer
XmlSerializer類存在於SystemXmlSerialization命名空間的SystemXmldll中 它用一種高度松散耦合的方式提供串行化服務 你的類不需要繼承特別的基類 而且它們也不需要實現任何特別的接口 相反的 你只需要在你的類或者這些類的公共域以及讀/寫屬性裡加上自定義的屬性 XmlSerializer 通過相反映射讀取這些屬性並用它們將你的類和類成員映射到XML元素和屬性
將XML 映射到對象
考慮表A中的XML語句 哪一個正確的描述了一家電影院中上映的電影呢?
表A
<?xml version=
encoding=
utf
?>
<theater>
<name>The Camelot</name>
<phone>(
)
</phone>
<movie minutes=
stars=
>
<title>The Score</title>
<rating>R</rating>
<showing>
:
:
</showing>
<showing>
:
:
</showing>
<showing>
:
:
</showing>
</movie>
<movie minutes=
>
<title>Shrek</title>
<rating>PG
</rating>
<showing>
:
:
</showing>
<showing>
:
:
</showing>
<showing>
:
:
</showing>
</movie>
</theater>
表B中定義了一個Theater(電影院)類 它包含了XmlSerializer使用的屬性映射
表B
using System;
using System
Xml
Serialization;
namespace Articles
TechRepublic
XmlSerialization
{
[XmlRoot(
theater
)]
public class Theater
{
[XmlElement(
name
)]
public string Name =
;
[XmlElement(
phone
)]
public string Phone =
;
[XmlElement(
movie
)]
public Movie[] Movies;
public override string ToString()
{
string movies =
;
if ( Movies != null )
foreach ( Movie movie in Movies )
movies +=
+ movie
ToString();
return String
Format(
Name
Phone
movies );
}
}
XmlRoot 屬性將類Theater映射到XML的根元素theater XmlElement 屬性將Name Phone 和 Movies數據域映射到嵌套在theater元素中的name phone 和 movie XML元素上去 因為Movies是Movie數組 所以XmlSerializer將它映射到多個XML movie元素
表C展示了一個帶有屬性映射的Movie類
表C
public class Movie
{
[XmlElement(
title
)]
public string Title =
;
[XmlAttribute(
minutes
)]
public uint Minutes =
;
[XmlElement(
showing
DataType=
time
)]
public DateTime[] Showings;
public override string ToString()
{
string showings =
;
if ( Showings != null )
{
showings =
shows at
;
foreach ( DateTime showing in Showings )
showings += showing
ToShortTimeString() +
;
}
else
{
showings =
No showings
;
}
return String
Format(
( min)
Title
Minutes
showings );
}
}
XmlElement 屬性將Title和Showings數據域映射到movie元素內的title 和showing XML元素就象 TheaterMovie一樣 做為DateTime數組的MovieShowings 被映射到多個XML showing 元素 showing 數據域的屬性包括位置屬性參數DataType=time 它將DateTime值映射到一個XML time值 其間去掉了日期信息而只保留了時間信息 XmlAttribute 屬性將Minutes 數據域映射到XML屬性而不是XML元素
XML數據中的moviestars(影星)屬性和rating(上座率)元素沒有被映射到Movie類中的任何東西上去 當反串行化XML數據的時候 XmlSerializer只是簡單的跳過它不能映射的項目 當串行化一個對象的時候 你可以在公共數據域和你希望XmlSerializer跳過的屬性裡加上XmlIgnore 屬性
XmlRoot XmlElement 和 XmlAttribute的屬性類都應包括後綴Attribute 在我的屬性申明裡 我使用了沒有後綴的縮寫形式 Theater和Movie類中的公共屬性可以被改寫成公共屬性以求得更好的封裝性 XmlSerializer 可以用相同的方式使用它們 我在這裡將它們做為數據域使用是為了使代碼更緊湊
將XML數據反串行化成對象
將XML數據加載到一個Theater對象裡現在已經變得非常容易 表D中的程序 XmlIn 通過反串行化movie showings XML 數據創建一個Theater對象 這個程序通過命令行執行 你需要指明一個輸入的XML文件
表D
using System;
using System
Xml
Serialization;
using System
IO;
using Articles
TechRepublic
XmlSerialization;
public class XmlIn
{
public static void Main( string[] args )
{
if ( args
Length !=
)
{
Console
WriteLine(
Usage: XmlIn infile
xml
);
return;
}
try
{
// Deserialize the specified file to a Theater object
XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );
FileStream fs = new FileStream( args[
]
FileMode
Open );
Theater theater = (Theater)xs
Deserialize( fs );
// Display the theater object
Console
WriteLine ( theater );
}
catch ( Exception x )
{
Console
WriteLine(
Exception:
+ x
Message );
}
}
}
Output:
>XmlIn theaterIn
xml
The Camelot
(
)
The Score (
min) shows at
:
PM
:
PM
:
PM
Shrek (
min) shows at
:
PM
:
PM
:
PM
主要的程序代碼都放在Main 函數的try代碼段裡 首先創建一個XmlSerializer對象並指明一個SystemType 對象來告訴反串行化程序要創建的對象的類型 typeof操作符為Theater類返回一個SystemType 對象 然後 打開一個文件流讀取輸入的XML文件 調用XmlSerializer的Deserialize方法 並把文件流傳遞給它 Deserialize 返回對Theater對象的引用 Theater和Movie 對象中的ToString方法能夠讓你簡單的輸出它們
將對象串行化到XML裡
從一個Theater對象生成XML數據同樣是容易的 表E中的程序XmlOut 就是將一個Theater對象串行化到XML 文件裡 這個程序通過命令行執行 你需要指明輸出的XML文件
表E
using System;
using System
Xml;
using System
Xml
Serialization;
using System
IO;
using Articles
TechRepublic
XmlSerialization;
public class XmlOut
{
// Returns a populated Theater object
public static Theater GetTheater()
{
Movie movie = new Movie();
movie
Title =
O Brother
Where Art Thou?
;
movie
Minutes =
;
movie
Showings = new DateTime[
];
movie
Showings[
] = new DateTime(
);
movie
Showings[
] = new DateTime(
);
movie
Showings[
] = new DateTime(
);
Theater theater = new Theater();
theater
Name =
Hollywood Movies
;
theater
Phone =
(
)
;
theater
Movies = new Movie[
];
theater
Movies[
] = movie;
return theater;
}
public static void Main( string[] args )
{
if ( args
Length !=
)
{
Console
WriteLine(
Usage: XmlOut outfile
xml
);
return;
}
try
{
Theater theater = GetTheater();
// Serialize the Theater object to an XML file
XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );
FileStream fs = new FileStream( args[
]
FileMode
Create );
xs
Serialize( fs
theater );
}
catch ( Exception x )
{
Console
WriteLine(
Exception:
+ x
Message );
}
}
}
Invocation:
>XmlOut theaterOut
xml
theaterOut
xml contents:
<?xml version=
?>
<theater
xmlns:xsi=
instance
xmlns:xsd=
>
<name>Hollywood Movies
</name>
<phone>(
)
</phone>
<movie minutes=
>
<title>O Brother
Where Art Thou?</title>
<showing>
:
:
:
</showing>
<showing>
:
:
:
</showing>
<showing>
:
:
:
</showing>
</movie>
</theater>
主要的程序代碼都放在Main 函數的try代碼段裡 首先通過GetTheater幫助函數創建一個Theater對象 然後 打開一個文件流來生成輸出的XML 文件 調用XmlSerializer的Serialize方法 傳遞給它文件流和Theater對象 就是這樣簡單XML文件生成了!
輸出的theater 元素包含了為模板和模板實例命名空間生成的XML命名空間屬性(xmlns) 雖然在這兩個命名空間裡這些數據並不代表任何東西 showing元素中的: 指的是美國中部時間 或者說GMT時間再減去個小時 也就是我所在的時區
移動數據是小菜一碟
XmlSerializer 使得在對象和XML間移動數據變得非常容易 只要在類裡加上XML映射屬性 但是對於更復雜的對象模型 手工的創建XML映射會變得非常的麻煩而且容易出錯 在我的下一篇文章裡 我將告訴你如何自動化這個工作並實現對你的XML數據的更嚴格的控制
From:http://tw.wingwit.com/Article/program/net/201311/11441.html