欢迎光临
我们一直在努力

建站超值云服务器,限时71元/月

人们一直高喊xml是解决系统互联问题的关键, 而.net framework 也为处理xml数据提供了许多不同的类库. xmldocument 类能让你像处理文件一样处理xml 数据, 而xmlreader, xmlwriter, 和它们的派生类使你能够将xml 数据做为数据流处理. xmlserializer 则提供了另外的方法, 它使你能够将自己的对象串行和反串行化为xml. 串行化数据既能够让你像处理文件一样对数据进行随机存取, 同时又能够跳过你不感兴趣的元素. 在本文中, 我将向你展示如何使用xmlserializer类以及如何在你的类中添加属性来控制串行化过程.

xmlserializer
xmlserializer类存在于system.xml.serialization命名空间的system.xml.dll中, 它用一种高度松散耦合的方式提供串行化服务. 你的类不需要继承特别的基类, 而且它们也不需要实现任何特别的接口. 相反的, 你只需要在你的类或者这些类的公共域以及读/写属性里加上自定义的属性. xmlserializer 通过相反映射读取这些属性并用它们将你的类和类成员映射到xml元素和属性.

将xml 映射到对象
考虑表a中的xml语句, 哪一个正确的描述了一家电影院中上映的电影呢?

表a

<?xml version="1.0" encoding="utf-8" ?>
<theater>
<name>the camelot</name>
<phone>(888)665-2222</phone>
<movie minutes="120" stars="2">
  <title>the score</title>
  <rating>r</rating>
  <showing>16:15:00</showing>
  <showing>19:05:00</showing>
  <showing>21:40:00</showing>
</movie>
<movie minutes="100">
  <title>shrek</title>
  <rating>pg-13</rating>
  <showing>16:00:00</showing>
  <showing>19:00:00</showing>
  <showing>21:40:00</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 += "\n" + movie.tostring();

                    return string.format( "{0}\n {1}\n{2}",
                    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 = 0;

    [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( " {0} ({1} min) {2}",
        title, minutes, showings );
    }
}

 

xmlelement 属性将title和showings数据域映射到movie元素内的title 和showing xml元素.就象 theater.movie一样, 做为datetime数组的movie.showings 被映射到多个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 != 1 )
        {
            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[0], 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
(888)665-2222

the score (120 min) shows at 4:15 pm 7:05 pm 9:40 pm
shrek (100 min) shows at 4:00 pm 7:00 pm 9:40 pm
 

主要的程序代码都放在main 函数的try代码段里. 首先创建一个xmlserializer对象并指明一个system.type 对象来告诉反串行化程序要创建的对象的类型. typeof操作符为theater类返回一个system.type 对象. 然后, 打开一个文件流读取输入的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 = 102;
        movie.showings = new datetime[3];
        movie.showings[0] = new datetime( 2001, 8, 2, 13, 15, 0 );
        movie.showings[1] = new datetime( 2001, 8, 2, 16, 30, 0 );
        movie.showings[2] = new datetime( 2001, 8, 2, 19, 55, 0 );

        theater theater = new theater();
        theater.name = "hollywood movies 10";
        theater.phone = "(972)555-154";
        theater.movies = new movie[1];
        theater.movies[0] = movie;

        return theater;
    }

    public static void main( string[] args )
    {
        if ( args.length != 1 )
        {
            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[0], filemode.create );

            xs.serialize( fs, theater );
        }
        catch ( exception x )
        {
            console.writeline( "exception: " + x.message );
        }
    }
}

invocation:
>xmlout theaterout.xml

theaterout.xml contents:

<?xml version="1.0"?>
<theater
xmlns:xsi=http://www.w3.org/2001/xmlschema-instance
xmlns:xsd="http://www.w3.org/2001/xmlschema">

    <name>hollywood movies 10</name>
    <phone>(972)555-154</phone>
    <movie minutes="102">
        <title>o brother, where art thou?</title>
        <showing>13:15:00.0000000-06:00</showing>
        <showing>16:30:00.0000000-06:00</showing>
        <showing>19:55:00.0000000-06:00</showing>
    </movie>
</theater>

 

主要的程序代码都放在main 函数的try代码段里. 首先通过gettheater帮助函数创建一个theater对象. 然后, 打开一个文件流来生成输出的xml 文件. 调用xmlserializer的serialize方法, 传递给它文件流和theater对象. 就是这样简单–xml文件生成了!

输出的theater 元素包含了为模板和模板实例命名空间生成的xml命名空间属性(xmlns), 虽然在这两个命名空间里这些数据并不代表任何东西. showing元素中的-06:00 指的是美国中部时间, 或者说gmt时间再减去个小时, 也就是我所在的时区.

移动数据是小菜一碟
xmlserializer 使得在对象和xml间移动数据变得非常容易, 只要在类里加上xml映射属性. 但是对于更复杂的对象模型, 手工的创建xml映射会变得非常的麻烦而且容易出错. 在我的下一篇文章里, 我将告诉你如何自动化这个工作并实现对你的xml数据的更严格的控制.

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 »
分享到: 更多 (0)

相关推荐

  • 暂无文章