在谈XML序列化之前,我们先来说说序列化。
序列化名词解释:序列化是将对象状态转换为可保持或传输的格式的过程。
与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。这就是序列化的意义所在。
我们可以把对象序列化为不同的格式,比如说,Json序列化、XML序列化、二进制序列化、SOAP序列化等,以上这些不同的格式也都是为了适应具体的业务需求。
在本篇文章中,我们就来分析一下XML的序列化和反序列化。我们先来看一个XML文件:
<?xmlversion="1.0"encoding="utf-8"?> <BaseInfo> <Person> <Name>小明</Name> <Age>16</Age> <Books> <Book> <ISBN>123</ISBN> <Title>借的书1</Title> </Book> </Books> </Person> <Person> <Name>小红</Name> <Age>18</Age> <Books> <Book> <ISBN>456</ISBN> <Title>借的书2</Title> </Book> <Book> <ISBN>789</ISBN> <Title>借的书3</Title> </Book> </Books> </Person> </BaseInfo>
在这个文件中BaseInfo为该XML的跟节点,它的里面由多个Person节点组成,在Person节点中又包括Name、Age、Books节点,Books节点中又由多个Book组成,在Book中又包括ISBN和Title。
下面首先我们要做的是创建与该XML相对应的对象,然后把对象转换为上述XML(序列化),或者把上述XML转换为对象(反序列化)。下面的例子中只是把XML存到本地,再从本地读取出来,如果需要在网络中传输,应该添加Serializable属性,我们先来创建对象。
usingSystem.Xml.Serialization; publicclassBaseInfo { List<Person>perList=newList<Person>(); [XmlElement(ElementName="Person")] publicList<Person>PerList { get{returnperList;} set{perList=value;} } }
使用XML序列化需要引入命名空间System.Xml.Serialization。我们创建的类名称为BaseInfo,这里与XML的跟节点需要对应,当然我们也可以指定该类转换为XML时映射成的名称,这里可以使用XmlRoot中的ElementName来指定它的名称,就像该类中的属性PerList那样应用,当然你也可以使用比较省事的方法,类的名称和XML节点的名称相同即可,就像该例子中一样。在BaseInfo类中,我们维护了一个PerList它是一个Person对象的集合,当然这个属性的名称并不与XML文件中的对应,所以要更改它的名称为Person。
好,接下来我们看看Person类:
usingSystem.Xml.Serialization; publicclassPerson { stringname; intage; List<Books>bookList=newList<Books>(); ///<summary> ///必须有默认的构造函数 ///</summary> publicPerson() {} publicPerson(stringname,intage) { this.name=name; this.age=age; } publicstringName { get{returnname;} set{name=value;} } publicintAge { get{returnage;} set{age=value;} } [XmlElement(ElementName="Books")] publicList<Books>BookList { get{returnbookList;} set{bookList=value;} } }
在该类中有Name和Age,还有维护了一个Books对象。
我们再来看看Books:
usingSystem.Xml.Serialization; publicclassBooks { List<Book>bookList=newList<Book>(); [XmlElement(ElementName="Book")] publicList<Book>BookList { get{returnbookList;} set{bookList=value;} } }
Books的作用就像是一个过渡的类,只为了与XML中的节点Books对应,在该类中维护了Book类的对象集合。
那么,最后我们来看Book类:
usingSystem.Xml.Serialization; publicclassBook { stringisbn; stringtitle; publicBook(){} publicBook(stringisbn,stringtitle) { this.isbn=isbn; this.title=title; } publicstringISBN { get{returnisbn;} set{isbn=value;} } publicstringTitle { get{returntitle;} set{title=value;} } }
好了,这样我们需要的类也就都创建完了,虽说创建类的过程有些繁杂,但是有了这些类,我们也就不用一个一个处理XML的节点了。我们创建一个简单的控制台程序,在里面添加两个处理方法,第一个是序列化方法:
publicstaticvoidxmlSerialize() { Bookb1=newBook("111","书1"); Bookb2=newBook("222","书2"); Bookb3=newBook("333","书3"); Booksbs1=newBooks(); Booksbs2=newBooks(); bs1.BookList.Add(b1); bs1.BookList.Add(b2); bs2.BookList.Add(b3); Personp1=newPerson("张三",11); Personp2=newPerson("李四",22); p1.BookList.Add(bs1); p2.BookList.Add(bs2); BaseInfobaseInfo=newBaseInfo(); baseInfo.PerList.Add(p1); baseInfo.PerList.Add(p2); StringWritersw=newStringWriter(); //创建XML命名空间 XmlSerializerNamespacesns=newXmlSerializerNamespaces(); ns.Add("",""); XmlSerializerserializer=newXmlSerializer(typeof(BaseInfo)); serializer.Serialize(sw,baseInfo,ns); sw.Close(); Console.Write(sw.ToString()); }
第二个是反序列化方法:
publicstaticvoidxmlDeserialize() { //xml来源可能是外部文件,也可能是从其他系统获得 FileStreamfile=newFileStream(@"http://www.cnblogs.com/info.xml",FileMode.Open,FileAccess.Read); XmlSerializerxmlSearializer=newXmlSerializer(typeof(BaseInfo)); BaseInfoinfo=(BaseInfo)xmlSearializer.Deserialize(file); file.Close(); foreach(Personperininfo.PerList) { Console.WriteLine("人员:"); Console.WriteLine("姓名:"+per.Name); Console.WriteLine("年龄:"+per.Age); foreach(Booksb1inper.BookList) { foreach(Bookbinb1.BookList) { Console.WriteLine("书:"); Console.WriteLine("ISBN:"+b.ISBN); Console.WriteLine("书名:"+b.Title); } } } }