[.net 面向對象程序設計進階] (10) 序列化(Serialization)(二) 經過序列化博客園文章學習XML的序列化html
本節導讀:編程
上節咱們介紹了二進制流的序列化,本節繼續上節內容介紹XML序列化和反序列化。XML做爲W3C標準數據傳輸格式,將XML對象化處理,認識和使用XML序列化類XmlSerializer,是.NET面向對象程序設計必需要掌握的知識。數組
讀前必備:函數
A.修飾符 [.net 面向對象編程基礎] (8) 基礎中的基礎——修飾符 post
B.類和類的實例 [.net 面向對象編程基礎] (9) 類和類的實例學習
C.類的成員 [.net 面向對象編程基礎] (10) 類的成員(字段、屬性、方法)this
D.數組與集合 [.net 面向對象編程基礎] (17) 數組與集合編碼
E.泛型 [.net 面向對象編程基礎] (18) 泛型spa
F.LINQ使用 [.net 面向對象編程基礎] (20) LINQ使用.net
1. 關於XML
XML 指可擴展標記語言(EXtensible Markup Language)
XML 是一種標記語言,很相似 HTML
XML 的設計宗旨是傳輸數據,而非顯示數據
XML 標籤沒有被預約義。您須要自行定義標籤。
XML 被設計爲具備自我描述性。
XML 是 W3C 的推薦標準
關於XML相關的基礎知識,這裏不做爲重點贅述,下面入正題。
2. XML序列化
XML序列化的命名空間是:System.Xml.Serialization
類:XmlSerializer
主要方法:Serialize和Deserialize
下面先來一個簡單有意思的XML序列化,爲了讓小夥伴們有興趣看完,我來實現動態獲取博客園實時數據(這個不是重點,本節重在在於序列化和反序列化),進行序列化。
首先獲取獲博客園文章,建立文章實體類,以下:
public class MyBlogs { /// <summary> /// 獲取個人博客園中文章 /// </summary> /// <returns></returns> public static List<MyArticle> GetMyArticle(int count) { var document = XDocument.Load( "http://wcf.open.cnblogs.com/blog/u/yubinfeng/posts/1/" + count ); List<MyArticle> myArticleList = new List<MyArticle>(); var elements = document.Root.Elements(); //在進行這個工做以前,咱們先獲取我博客中的文章列表 var result = elements.Where(m => m.Name.LocalName == "entry").Select(myArticle => new MyArticle { id = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "id").Value), title = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "title").Value, published = Convert.ToDateTime(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "published").Value), updated = Convert.ToDateTime(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "updated").Value), diggs = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "diggs").Value), views = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "views").Value), comments = Convert.ToInt32(myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "comments").Value), summary = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "summary").Value, link = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "link").Attribute("href").Value, author = myArticle.Elements().SingleOrDefault(x => x.Name.LocalName == "author").Elements().SingleOrDefault(x => x.Name.LocalName == "name").Value }).OrderByDescending(m=>m.published); myArticleList.AddRange(result); return myArticleList; } } /// <summary /// 個人博客文章實體類 /// </summary> public class MyArticle { /// <summary> /// 文章編號 /// </summary> public int id { get; set; } /// <summary> /// 文章標題 /// </summary> public string title { get; set; } /// <summary> /// 文章摘要 /// </summary> public string summary { get; set; } /// <summary> /// 發佈時間 /// </summary> public DateTime published { get; set; } /// <summary> /// 最後更新時間 /// </summary> public DateTime updated { get; set; } /// <summary> /// URL地址 /// </summary> public string link { get; set; } /// <summary> /// 推薦數 /// </summary> public int diggs { get; set; } /// <summary> /// 瀏覽量 /// </summary> public int views { get; set; } /// <summary> /// 評論數 /// </summary> public int comments { get; set; } /// <summary> /// 做者 /// </summary> public string author { get; set; } }
下面實現myArticleList對象序列化XML並輸出到控制檯
//XML序列化命名空間:System.Xml.Serialization; //類:XmlSerializer //主要方法:Serialize和Deserialize //博客數據的對象化(反序列化)及序列化 //(1)獲取我博客園中最後10篇文章 (實際上這個過程也是反序列化) List<MyArticle> myArticleList = MyBlogs.GetMyArticle(10); //(2)將上面的對象myArticleList序列化XML,並輸出到控制檯 string xmlString = String.Empty; using (MemoryStream ms = new MemoryStream()) { XmlSerializer xml = new XmlSerializer(typeof(List<MyArticle>)); xml.Serialize(ms, myArticleList); byte[] arr = ms.ToArray(); xmlString = Encoding.UTF8.GetString(arr, 0, arr.Length); ms.Close(); } Console.WriteLine(xmlString);
運行結果以下:
上面的示例,實現了一個最基本的從對象到XML的序列化。接下來完成上面示例序列化的xmlString文本對象化爲List<MyArticle>
3. XML反序列化
Xml反序列化,即將Xml文本轉化爲對象的過程。
咱們將上面序列化的文本xmlString反序列化爲List<MyArticle>對象
//下面咱們剛纔輸出的xmlString文本對象化(反序列化)爲一個文章List對象 using (StringReader sr = new StringReader(xmlString)) { XmlSerializer xml=new XmlSerializer(typeof(List<MyArticle>)); ; List<MyArticle> myNewArticleList= xml.Deserialize(sr) as List<MyArticle>; //遍歷輸出反序化的新對象myNewArticleList myNewArticleList.ForEach(m => Console.WriteLine("文章編號:" + m.id + "\n文章標題:" + m.title) ); sr.Close(); }
運行結果以下:
上面的示例實現了從XML文本反序列化爲List<MyArticle>對象的過程。
學會了上面的兩個示例,就掌握了XML序列化和反序列化的基本知識,下面介紹更進一步介紹在序列化過程當中的一些細節。
4. XML序列化一些注意事項
(1)要序列化的類必須有默認的構造的構造函數,才能使用XmlSerializer序列化,須要序列化的類都必須有一個無參的構造函數(經過對基礎中類和類的實例學習,咱們必須知道類不定義構造函數的狀況下,會默認生成一個無參數的構造函數);
(2)索引器、私有字段或只讀屬性(只讀集合屬性除外)不能被序列化;
(3)不想序列化時:當不想序列化一個屬性時,使用[System.Xml.Serialization.XmlIgnore]標記,能用於屬性;[NonSerializable]應用於屬性無效,能用於類,結構體等;
(4)方法不能被序列化(雖然是廢話,可是仍是列舉出來);
(5)枚舉變量可序列化爲字符串,無需用[XmlInclude]
(6)導出非基本類型對象,都必須用[XmlInclude]事先聲明。該規則遞歸做用到子元素
(7)Attribute中的IsNullable參數若等於false,表示若元素爲null則不顯示該元素。(針對值類型有效)
(8)某些類就是沒法XML序列化的(即便使用了[XmlInclude])
好比:
IDictionary(如HashTable);
父類對象賦予子類對象值的狀況;
對象間循環引用;
(9)對於沒法XML序列化的對象,可考慮:
使用自定義xml序列化(實現IXmlSerializable接口);
實現IDictionary的類,可考慮(1)用其它集合類替代;(2)用類封裝之,並提供Add和this函數;
某些類型須要先通過轉換,而後才能序列化爲 XML。如XML序列化System.Drawing.Color,可先用ToArgb()將其轉換爲整數;
過於複雜的對象用xml序列化不便的話,可考慮用二進制序列化;
(10)默認構造函數是必須的,由於反序列化本質上使用的是反射,須要默認構造函數來實例化類,若是去掉其中的默認構造函數,則編譯沒有問題,但運行就會報錯。
儘可能不要將比較大的屬性放在默認構造函數初始化,那會致使在反序列化時對列表初始化兩次:默認構造函數中執行一次,反序列化時從XML文檔讀取再執行一次。
以上十點注意,其中前三點,也就是加黑的這幾點,是重點要知道的。
5. 改變XML序列化的默認值
5.1 更改或刪除XML默認命名空間
使用 XmlSerializerNamespaces類(System.Xml.Serialization.XmlSerializerNamespaces)。來完成
咱們對上面最重獲得的對象List<MyArticle>進行XML序列化,並更改XML默認的命名空間,示例以下:
//更新默認命名空間 //使用XmlSerializerNamespaces類來完成(System.Xml.Serialization.XmlSerializerNamespaces) System.Xml.Serialization.XmlSerializerNamespaces XmlSN = new XmlSerializerNamespaces(); //獲取文章列表對象 List<MyArticle> newArticleList = MyBlogs.GetMyArticle(10); //更改命名空間,並輸出 string newXmlString = String.Empty; XmlSN.Add("MyBlogURL", @"http://www.cnblogs.com/yubinfeng"); using (MemoryStream ms = new MemoryStream()) { XmlSerializer xml = new XmlSerializer(typeof(List<MyArticle>)); xml.Serialize(ms, newArticleList,XmlSN); byte[] arr = ms.ToArray(); newXmlString = Encoding.UTF8.GetString(arr, 0, arr.Length); ms.Close(); } Console.WriteLine(newXmlString);
咱們能夠和前面默認的輸出結果比較,以下圖:
也是能夠刪除命名空間的
System.Xml.Serialization.XmlSerializerNamespaces XmlSN = new XmlSerializerNamespaces(); XmlSN.Add("","");
當加入一個空的命名空間時,就能夠刪除默認的XML命名空間。
5.2 更改XML序列化的其餘元素
咱們先列出XmlWriterSettings能夠更改的屬性。
XmlWriterSettings更多設置屬性以下:
成員 |
說明 |
CloseOutput |
獲取或設置一個值,該值指示在調用 Close 方法時,XmlWriter 是否還應該關閉基礎流或 TextWriter。 |
Encoding |
獲取或設置要使用的文本編碼的類型。 |
Indent |
獲取或設置一個值,該值指示是否縮進元素。 |
IndentChars |
獲取或設置縮進時要使用的字符串。 |
NamespaceHandling |
獲取或設置一個值,該值指示在編寫 XML 內容時,XmlWriter 是否應移除重複的命名空間聲明。 的默認是輸出程序中出現的全部命名空間聲明。 |
NewLineChars |
獲取或設置要用於分行符的字符串 |
NewLineHandling |
獲取或設置一個值,該值指示是否將輸出中的分行符正常化。 |
NewLineOnAttributes |
獲取或設置一個值,該值指示是否將屬性寫入新行。 |
OmitXmlDeclaration |
獲取或設置一個值指示省略 XML 聲明。 |
Encoding |
獲取或設置要使用的文本編碼的類型。 |
Reset方法 |
重置以上屬性 |
API官方地址:http://msdn.microsoft.com/zh-cn/library/system.xml.xmlwritersettings(v=vs.110).aspx
下面咱們經過示例。來設置三個屬性:去掉XML聲明,換行縮進,指定字符縮進,示例以下:
先定義一個方法
/// <summary> /// 設置三個屬性:去掉XML聲明,指定字符縮進 /// </summary> /// <param name="Obj"></param> /// <returns></returns> public static string ObjectToXmlSerializer(Object Obj) { System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings(); settings.OmitXmlDeclaration = true;//去除xml聲明 settings.Encoding = Encoding.Default;//使用默認編碼 settings.IndentChars = "--"; //使用指定字符縮進 settings.Indent = true; //換行縮進 System.IO.MemoryStream mem = new MemoryStream(); using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(mem, settings)) { //去除默認命名空間xmlns:xsd和xmlns:xsi XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlSerializer formatter = new XmlSerializer(Obj.GetType()); formatter.Serialize(writer, Obj, ns); } return Encoding.Default.GetString(mem.ToArray()); }
調用以下:
//使用 設置 XmlWriterSettings 類的屬性,來更改序列化的XML其餘元素 //所在命名空間:System.Xml.XmlWriterSettings //設置三個屬性:去掉XML聲明,指定字符縮進 Console.WriteLine(ObjectToXmlSerializer(myArticleList));
輸出結果和以前進行對比,以下圖:
6. 本節要點:
(1)瞭解XML的序列化,將對象轉爲XML數據格式
(2)瞭解XML的反序列化,將XML文本轉換爲對象
(3)瞭解XML序更化的注意事項,主要有如下幾點:
(4)改變XML序列化的默認值:
使用 XmlSerializerNamespaces類(System.Xml.Serialization.XmlSerializerNamespaces),更改或刪除XML的命名空間;
使用 XmlWriterSettings類(System.Xml.XmlWriterSettings)的屬性,來更改XML的明名、縮進等元素。
下節咱們將對經過實現序列化接口IXmlSerializable來介紹XML序列化以及介紹XML基本操做,並舉例說明,最後會整理一個XML操做的通用類。
==============================================================================================
<若是對你有幫助,記得點一下推薦哦,若有有不明白或錯誤之處,請多交流>
<對本系列文章閱讀有困難的朋友,請先看《.net 面向對象編程基礎》>
<轉載聲明:技術須要共享精神,歡迎轉載本博客中的文章,但請註明版權及URL>
==============================================================================================