[.net 面向對象程序設計進階] (10) 序列化(Serialization)(二) 經過序列化博客園文章學習XML的序列化

[.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序更化的注意事項,主要有如下幾點:

  • 默認類和無參數構造函數類才能夠序列化;
  • 索引器、私有字段或只讀屬性(只讀集合屬性除外)不能被序列化
  • 有一些序列化的標記當不想序列化一個屬性時,使用[System.Xml.Serialization.XmlIgnore]標記,能用於屬性;
  • [NonSerializable]應用於屬性無效,能用於類,結構體等。

(4)改變XML序列化的默認值:

使用 XmlSerializerNamespaces類(System.Xml.Serialization.XmlSerializerNamespaces),更改或刪除XML的命名空間;

使用 XmlWriterSettings類(System.Xml.XmlWriterSettings)的屬性,來更改XML的明名、縮進等元素。 

     下節咱們將對經過實現序列化接口IXmlSerializable來介紹XML序列化以及介紹XML基本操做,並舉例說明,最後會整理一個XML操做的通用類

==============================================================================================  

 返回目錄

 <若是對你有幫助,記得點一下推薦哦,若有有不明白或錯誤之處,請多交流>  

<對本系列文章閱讀有困難的朋友,請先看《.net 面向對象編程基礎》>

<轉載聲明:技術須要共享精神,歡迎轉載本博客中的文章,但請註明版權及URL>

.NET 技術交流羣:467189533    .NET 程序設計

==============================================================================================   

相關文章
相關標籤/搜索