web前端

位置:IT落伍者 >> web前端 >> 浏览文章

如何使用XmlSerializer类控制串行化


发布日期:2018年07月14日
 
如何使用XmlSerializer类控制串行化

人们一直高喊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 SystemXmlSerialization;

namespace ArticlesTechRepublicXmlSerialization

{

[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 += + movieToString();

return StringFormat(

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 += showingToShortTimeString() + ;

}

else

{

showings = No showings;

}

return StringFormat( ( 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 SystemXmlSerialization;

using SystemIO;

using ArticlesTechRepublicXmlSerialization;

public class XmlIn

{

public static void Main( string[] args )

{

if ( argsLength != )

{

ConsoleWriteLine( Usage: XmlIn infilexml );

return;

}

try

{

// Deserialize the specified file to a Theater object

XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );

FileStream fs = new FileStream( args[] FileModeOpen );

Theater theater = (Theater)xsDeserialize( fs );

// Display the theater object

ConsoleWriteLine ( theater );

}

catch ( Exception x )

{

ConsoleWriteLine( Exception: + xMessage );

}

}

}

Output:

>XmlIn theaterInxml

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 SystemXml;

using SystemXmlSerialization;

using SystemIO;

using ArticlesTechRepublicXmlSerialization;

public class XmlOut

{

// Returns a populated Theater object

public static Theater GetTheater()

{

Movie movie = new Movie();

movieTitle = O Brother Where Art Thou?;

movieMinutes = ;

movieShowings = new DateTime[];

movieShowings[] = new DateTime( );

movieShowings[] = new DateTime( );

movieShowings[] = new DateTime( );

Theater theater = new Theater();

theaterName = Hollywood Movies ;

theaterPhone = ();

theaterMovies = new Movie[];

theaterMovies[] = movie;

return theater;

}

public static void Main( string[] args )

{

if ( argsLength != )

{

ConsoleWriteLine( Usage: XmlOut outfilexml );

return;

}

try

{

Theater theater = GetTheater();

// Serialize the Theater object to an XML file

XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );

FileStream fs = new FileStream( args[] FileModeCreate );

xsSerialize( fs theater );

}

catch ( Exception x )

{

ConsoleWriteLine( Exception: + xMessage );

}

}

}

Invocation:

>XmlOut theaterOutxml

theaterOutxml 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数据的更严格的控制

               

上一篇:XML入门基础:XML的语法规则

下一篇:用XMLTextReader类加速XML存取