c#操作Xml(八)
前言
??? 呃,已經是第八篇了,怎么感覺Xml還有好多東西沒講。。。還是先挑比較重要的東西講一下吧,今天的主角是.net的Xml序列化。
??? 在主角出現前,先回想一下,平時什么地方用了Xml序列化吧:
??? 第一個想到的當然是Web Service和更進一步的WCF,沒有Xml序列化的話,就需要手動處理Soap協議的各種輸入和輸出,其復雜性將會成倍的增長。
??? 第二個想到的就是Xml序列化其實就是一個Xml與對象之間的橋梁,可以把一個實例Xml變成一個實例對象,也可以把一個實例對象變成一個實例Xml,這在需要持久化的場合非常有用。
工具
??? 工欲善其事,必先利其器。首先來看看關于Xml序列化的工具吧。
??? 這些工具通常在X:\Program Files\Microsoft SDKs\Windows\v6.0A\bin目錄下,其中和Xml序列關系比較大的有xsd.exe、wsdl.exe、svcutil.exe。當然其他工具在.net里面也是非常重要的,可以在這里察看所有工具的用途和使用方式。這里重點要用到的是xsd.exe。
??? 當然這個工具有三種用法,分別是:
- Xml First,先有Xml實例,適合先想好Xml是什么樣,或者已經有Xml實例的情況
- Xsd First,先有Xsd,適合于可以獲得Xsd,或者熟悉Xsd的人,并且對Xml有很強的控制欲的人(某人飄過)
- Class First,先有c#類型,適合于先有c#代碼的情況
??? 接下來將分別介紹這3種方式的。
Xml First
??? 這種情況首先有一個Xml實例,例如:
<?xml version="1.0" encoding="utf-8" ?> <persons><person name="Zhenway, Yan"><goodat>Xml</goodat><goodat>Reflection</goodat></person><person name="Allen, Lee"><goodat>Ruby</goodat><goodat>F#</goodat><goodat>Windows Mobile</goodat><goodat>Linq</goodat></person> </persons>??? 利用Xsd命令:“xsd XmlFirst.xml”,就可以根據這個實例獲得xsd(當然不會是非常精確的,但基本上能用):
<?xml version="1.0" encoding="utf-8"?> <xs:schema id="persons" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"><xs:element name="persons" msdata:IsDataSet="true" msdata:Locale="en-US"><xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><xs:element name="person"><xs:complexType><xs:sequence><xs:element name="goodat" nillable="true" minOccurs="0" maxOccurs="unbounded"><xs:complexType><xs:simpleContent msdata:ColumnName="goodat_Text" msdata:Ordinal="0"><xs:extension base="xs:string"></xs:extension></xs:simpleContent></xs:complexType></xs:element></xs:sequence><xs:attribute name="name" type="xs:string" /></xs:complexType></xs:element></xs:choice></xs:complexType></xs:element> </xs:schema>??? 當然,如果對這個Xsd不太滿意的話,還可以修改一下。這樣就把Xml First轉換成Xsd First。
Xsd First
??? 這里首先需要一個Xsd(某個控制欲極強的人重新寫了一下xsd)
<?xml version="1.0" encoding="utf-8"?> <xs:schema id="persons" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema"><xs:complexType name="Person"><xs:sequence><xs:element name="goodat" type="xs:string" minOccurs="1" maxOccurs="unbounded"/></xs:sequence><xs:attribute name="name" type="xs:string"/></xs:complexType><xs:complexType name="Persons"><xs:sequence><xs:element name="person" type="Person" minOccurs="0" maxOccurs="unbounded"/></xs:sequence></xs:complexType><xs:element name="persons" type="Persons"/> </xs:schema>??? 這里要求每個person的goodat至少要有一項。
??? 然后利用xsd命令:“xsd XsdFirst.xsd /c”,這樣就可以獲得一個cs文件,整理后,如下:
using System; using System.CodeDom.Compiler; using System.ComponentModel; using System.Diagnostics; using System.Xml.Schema; using System.Xml.Serialization;[GeneratedCodeAttribute("xsd", "2.0.50727.1432")] [SerializableAttribute()] [DebuggerStepThroughAttribute()] [DesignerCategoryAttribute("code")] [XmlRootAttribute("persons", Namespace = "", IsNullable = false)] public partial class Persons {private Person[] personField;[System.Xml.Serialization.XmlElementAttribute("person", Form = XmlSchemaForm.Unqualified)]public Person[] person{get { return this.personField; }set { this.personField = value; }} }[GeneratedCodeAttribute("xsd", "2.0.50727.1432")] [SerializableAttribute()] [DebuggerStepThroughAttribute()] [DesignerCategoryAttribute("code")] public partial class Person {private string[] goodatField;private string nameField;[XmlElementAttribute("goodat", Form = XmlSchemaForm.Unqualified)]public string[] goodat{get { return this.goodatField; }set { this.goodatField = value; }}[XmlAttributeAttribute()]public string name{get { return this.nameField; }set { this.nameField = value; }} }??? 這樣就可以獲得一個類型與這個Xsd對應,在對象實例與這個Xsd實例之間建立一座橋梁。
Class First
??? 這種情況適合于先有類型,然后想持久化的情況,例如擁有一個下列的類型:
[XmlRoot("persons")] public class ClassFirst {[XmlElement("person")]public Person[] PersonCollection { get; set; } }public class Person {[XmlAttribute("name")]public string Name { get; set; }[XmlElement("goodat")]public string[] GoodAt { get; set; } }??? Build以后,執行命令:“xsd ClassFirstSample.dll”,就可以獲得這樣一個xsd:
<?xml version="1.0" encoding="utf-8"?> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"><xs:element name="persons" nillable="true" type="ClassFirst" /><xs:complexType name="ClassFirst"><xs:sequence><xs:element minOccurs="0" maxOccurs="unbounded" name="person" type="Person" /></xs:sequence></xs:complexType><xs:complexType name="Person"><xs:sequence><xs:element minOccurs="0" maxOccurs="unbounded" name="goodat" type="xs:string" /></xs:sequence><xs:attribute name="name" type="xs:string" /></xs:complexType><xs:element name="Person" nillable="true" type="Person" /> </xs:schema>??? 這個xsd就是序列化出來的xml的Schema,基本上與。
XmlSerializer
??? 前面的三種方式都只是在OOP與Xml之間建立一個契約,現在來介紹這個橋梁——XmlSerializer
??? 廢話就不說了,先來看看如何把對象轉換成xml:
XmlSerializer serializer = new XmlSerializer(typeof(Persons)); serializer.Serialize(Console.Out, new Persons {person = new Person[]{new Person{name = "Zhenway, Yan",goodat = new string[] { "Reflection", "Xml" },},new Person{name = "Allen, Lee",goodat = new string[] { "Ruby", "F#", "Windows Mobile", "Linq" },},} });??? 來看看輸出:
??? 很好,接下來看看如何反過來,從Xml獲得對象實例:
XmlSerializer serializer = new XmlSerializer(typeof(Persons)); using (var reader = File.OpenText("XmlFirst.xml")) {Persons ps = (Persons)serializer.Deserialize(reader);foreach (var p in ps.person){Console.WriteLine("name='{0}', good at={1}",p.name, string.Join(", ", p.goodat));} }??? 看看輸出:
??? 不過需要注意的一點是,如果需要反序列化對象的話,需要對臨時目錄(根據Windows的TEMP環境變量定義)的寫入權限。
??? 另外,XmlSerializer會自動生成一個Assembly用于加速序列化和反序列化,不過要注意由于AppDomain無法單獨卸載一個Assembly的特性,所以當產生過多的Assembly時,就會導致內存占用過多。
??? 盡管XmlSerializer也會盡量利用現有的Assembly,不過這僅僅發生在(Type)構造函數,和(Type,String)構造函數時才會發生,而其他構造函數將再次創建Assembly,如果放置在循環中,這樣將導致AppDomain中Assembly數量激增,因此緩存XmlSerializer在某些場合下是非常必要的。
??? 另外msdn上對XmlSerializer的描述有一處非常特別的地方,“此類型是線程安全的”,這在整個msdn中并不多見,也就是說,不用對緩存的XmlSerializer對象做任何的同步處理。
?
更多控制
??? XmlSerializer本身支持很多擴展,其中包括使用屬性控制 XML 序列化,和更加可定制化的IXmlSerializable接口,這里限于篇幅就省略相關的內容。
下集預告?
??? 第八篇了,還要下集?這個系列暫時就到這里吧,雖然感覺還有很多內容要講。。。之后將推出難度較高的進階系列。
系列目錄
另外整理出本系列之前幾篇連接和主要內容:
(一)——Dom
(二)——Dom with Namespace
(三)——Linq to Xml
(四)——Linq to Xml with Namespace
(五)——XStreamingElement
(六)——XmlWriter
(七)——XmlReader
總結
以上是生活随笔為你收集整理的c#操作Xml(八)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初步认识设计模式
- 下一篇: 命令行下一种新的加帐号的方法