XML序列化和反序列化

2021-08-21 12:15:58 字數 4393 閱讀 3739

閱讀目錄

回到頂部

由於.net framework針對xml提供了很多api,這些api根據不同的使用場景實現了不同層次的封裝,比如,我們可以直接使用xmltextreader、xmldocument、xpath來取數xml中的資料,也可以使用linq to xml或者反序列化的方法從xml中讀取資料。那麼,使用哪種方法最簡單呢?

我個人傾向於使用序列化,反序列化的方法來使用xml。採用這種方法,我只要考慮如何定義資料型別就可以了,讀寫xml各只需要一行呼叫即可完成。例如:

// 1. 首先要建立或者得到乙個資料物件

order order = getorderbyid(123);

// 2. 用序列化的方法生成xml

string xml = xmlhelper.xmlserialize(order, encoding.utf8);

// 3. 從xml讀取資料並生成物件

order order2 = xmlhelper.xmldeserialize(xml, encoding.utf8);

就是這麼簡單的事情,xml結構是什麼樣的,我根本不用關心,我只關心資料是否能儲存以及下次是否能將它們讀取出來。說明:xmlhelper是乙個工具類,全部源**如下:

或許有人會說:我使用xpath從xml讀取資料也很簡單啊。

我認為這種說法有乙個限制條件:只需要從xml中讀取少量的資料。

如果要全部讀取,用這種方法會寫出一大堆的機械**出來!所以,我非常反感用這種方法從xml中讀取全部資料。

回到頂部

如果是乙個新專案,我肯定會毫不猶豫的使用序列化和反序列化的方法來使用xml,然而,有時在維護乙個老專案時,面對一堆只有xml卻沒有與之對應的c#型別時,我們就需要根據xml結構來逆向推導c#型別,然後才能使用序列化和反序列化的方法。逆向推導的過程是麻煩的,不過,型別推導出來之後,後面的事情就簡單多了。

這裡有乙個xml檔案,是我從visual sutdio的安裝目錄中找到的:

怎樣用反序列化的方式來讀取它的資料呢,我在部落格的最後將給出完整的實現**。

現在,我們還是看一下這個xml有哪些特點吧。

對於這個節點來說,它包含了三個資料項(屬性):id,title,priority。這樣的linkgroup節點有三個。

類似的還有glyph節點。

asp.net home page
litem節點除了與linkgroup有著類似的資料(屬性)之外,還包含著乙個字串:asp.net home page ,這是另外一種資料的存放方式。

另外,linkgroup和litem都允許重複出現,我們可以用陣列或者列表(array,list)來理解它們。

我還發現一些巢狀關係:linkgroup可以包含glyph,context包含著links,links又包含了多個litem。

不管如何巢狀,我發現資料都是包含在乙個乙個的xml節點中。

如果用專業的單詞來描述它們,我們可以將id,title,priority這三個資料項稱為xmlattribute,litem,linkgroup節點稱為xmlelement,」asp.net home page「出現的位置可以稱為innertext。基本上,xml就是由這三類資料組成。

下面我來演示如何使用這三種資料項。

回到頂部

首先,我來定義乙個型別:

public class class1

public string strvalue

}

下面是序列化與反序列的呼叫**:

class1 c1 = new class1 ;

string xml = xmlhelper.xmlserialize(c1, encoding.utf8);

console.writeline(xml);

console.writeline("---------------------------------------");

class1 c2 = xmlhelper.xmldeserialize(xml, encoding.utf8);

console.writeline("intvalue: " + c2.intvalue.tostring());

console.writeline("strvalue: " + c2.strvalue);

執行結果如下:

<?xml version="1.0" encoding="utf-8"?>

3fish li

---------------------------------------

intvalue: 3

strvalue: fish li

結果顯示,intvalue和strvalue這二個屬性生成了xmlelement。

小結:預設情況下(不加任何attribute),型別中的屬性或者字段,都會生成xmlelement。

回到頂部

再來定義乙個型別:

public class class2

[xmlelement]

public string strvalue

}

注意,我在二個屬性上增加的不同的attribute.

下面是序列化與反序列的呼叫**:

執行結果如下(我將結果做了換行處理):

<?xml version="1.0" encoding="utf-8"?>

fish li

---------------------------------------

intvalue: 3

strvalue: fish li

結果顯示:

1. intvalue 生成了xmlattribute

2. strvalue 生成了xmlelement(和不加[xmlelement]的效果一樣,表示就是預設行為)。

小結:如果希望型別中的屬性或者字段生成xmlattribute,需要在型別的成員上用[xmlattribute]來指出。

回到頂部

還是來定義乙個型別:

public class class3

[xmltext]

public string strvalue

}

注意,我在strvalue上增加的不同的attribute.

下面是序列化與反序列的呼叫**:

執行結果如下(我將結果做了換行處理):

<?xml version="1.0" encoding="utf-8"?>

fish li

---------------------------------------

intvalue: 3

strvalue: fish li

結果符合預期:strvalue屬性在增加了[xmltext]之後,生成了乙個文字節點(innertext)

小結:如果希望型別中的屬性或者字段生成innertext,需要在型別的成員上用[xmltext]來指出。

回到頂部

看過前面幾個示例,大家應該能發現:通過序列化得到的xmlelement和xmlattribute都與型別的資料成員或者型別同名。然而有時候我們可以希望讓屬性名與xml的節點名稱不一樣,那麼就要使用【重新命名】的功能了,請看以下示例:

[xmltype("c4")]

public class class4

[xmlelement("name")]

public string strvalue

}

序列化與反序列的呼叫**前面已經多次看到,這裡就省略它們了。

執行結果如下(我將結果做了換行處理):

<?xml version="1.0" encoding="utf-8"?>

fish li

---------------------------------------

intvalue: 3

strvalue: fish li

看看輸出結果中的紅字粗體字,再看看型別定義中的三個attribute的三個字串引數,我想你能發現規律的。

小結:xmlattribute,xmlelement允許接受乙個別名用來控制生成節點的名稱,型別的重新命名用xmltype來實現。

Xml序列化和反序列化

1.xmlserializer 類 該類用一種高度鬆散耦合的方式提供序列化服務。你的類不需要繼承特別的基類,而且它們也不需要實現特別的介面。相反,你只需在你的類或者這些類的公共域以及讀 寫屬性裡加上自定義的特性。xmlserializer 通過反射機制讀取這些特性並用它們將你的類和類成員對映到 xm...

XML序列化和反序列化

在談xml序列化之前,我們先來說說序列化。為什麼要做序列化和反序列化?net程式執行時,物件都駐留在記憶體中 記憶體中的物件如果需要傳遞給其他系統使用 或者在關機時需要儲存下來以便下次再次啟動程式使用就需要序列化和反序列化。序列化名詞解釋 序列化是將物件狀態轉換為可保持或傳輸的格式的過程。與序列化相...

XML序列化和反序列化

不過在上篇中忘了把json序列化和反序列化的另外一種方式寫上去了,這裡做個簡單的補充 json篇 json序列化和反序列化擴充套件方法實現類 using system using system.collections.generic using system.linq using system.te...