c# XML和實(shí)體類之間相互轉(zhuǎn)換(序列化和反序列化)

我們需要在XML與實(shí)體類,DataTable,List之間進(jìn)行轉(zhuǎn)換,下面是XmlUtil類嗅虏,該類來自網(wǎng)絡(luò)并稍加修改。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
 
/// <summary>
/// Xml序列化與反序列化
/// </summary>
publicclass XmlUtil
{
    #region 反序列化
    /// <summary>
    /// 反序列化
    /// </summary>
    /// <param name="type">類型</param>
    /// <param name="xml">XML字符串</param>
    /// <returns></returns>
    publicstatic objectDeserialize(Type type, stringxml)
    {
        try
        {
            using(StringReader sr = newStringReader(xml))
            {
                XmlSerializer xmldes =new XmlSerializer(type);
                returnxmldes.Deserialize(sr);
            }
        }
        catch(Exception e)
        {
 
            returnnull;
        }
    }
    /// <summary>
    /// 反序列化
    /// </summary>
    /// <param name="type"></param>
    /// <param name="xml"></param>
    /// <returns></returns>
    publicstatic objectDeserialize(Type type, Stream stream)
    {
        XmlSerializer xmldes =new XmlSerializer(type);
        returnxmldes.Deserialize(stream);
    }
    #endregion
 
    #region 序列化
    /// <summary>
    /// 序列化
    /// </summary>
    /// <param name="type">類型</param>
    /// <param name="obj">對(duì)象</param>
    /// <returns></returns>
    publicstatic stringSerializer(Type type, objectobj)
    {
        MemoryStream Stream =new MemoryStream();
        XmlSerializer xml =new XmlSerializer(type);
        try
        {
            //序列化對(duì)象
            xml.Serialize(Stream, obj);
        }
        catch(InvalidOperationException)
        {
            throw;
        }
        Stream.Position = 0;
        StreamReader sr =new StreamReader(Stream);
        stringstr = sr.ReadToEnd();
         
        sr.Dispose();
        Stream.Dispose();
 
        returnstr;
    }
 
    #endregion
}
下面是測(cè)試代碼:
  1. 實(shí)體對(duì)象轉(zhuǎn)換到Xml
public class Student
{
    publicstring Name { set; get; }
    publicint Age { set;get; }
}
 
Student stu1 = new Student() { Name ="okbase", Age = 10 };
string xml = XmlUtil.Serializer(typeof(Student), stu1);
Console.Write(xml);
  1. Xml轉(zhuǎn)換到實(shí)體對(duì)象
Student stu2 = XmlUtil.Deserialize(typeof(Student), xml)as Student;
Console.Write(string.Format("名字:{0},年齡:{1}", stu2.Name, stu2.Age));
  1. DataTable轉(zhuǎn)換到Xml
// 生成DataTable對(duì)象用于測(cè)試
DataTable dt1 = new DataTable("mytable");  // 必須指明DataTable名稱
 
dt1.Columns.Add("Dosage",typeof(int));
dt1.Columns.Add("Drug",typeof(string));
dt1.Columns.Add("Patient",typeof(string));
dt1.Columns.Add("Date",typeof(DateTime));
 
// 添加行
dt1.Rows.Add(25,"Indocin", "David", DateTime.Now);
dt1.Rows.Add(50,"Enebrel", "Sam", DateTime.Now);
dt1.Rows.Add(10,"Hydralazine","Christoff", DateTime.Now);
dt1.Rows.Add(21,"Combivent","Janet", DateTime.Now);
dt1.Rows.Add(100,"Dilantin", "Melanie", DateTime.Now);
 
// 序列化
xml = XmlUtil.Serializer(typeof(DataTable), dt1);
Console.Write(xml);
  1. Xml轉(zhuǎn)換到DataTable
// 反序列化
DataTable dt2 = XmlUtil.Deserialize(typeof(DataTable), xml)as DataTable;
 
// 輸出測(cè)試結(jié)果
foreach(DataRow dr indt2.Rows)
{
    foreach(DataColumn col indt2.Columns)
    {
        Console.Write(dr[col].ToString() +" ");
    }
 
    Console.Write("\r\n");
}
  1. List轉(zhuǎn)換到Xml
// 生成List對(duì)象用于測(cè)試
List<Student> list1 =new List<Student>(3);
 
list1.Add(newStudent() { Name = "okbase", Age = 10 });
list1.Add(newStudent() { Name = "csdn", Age = 15 });
// 序列化
xml = XmlUtil.Serializer(typeof(List<Student>), list1);
Console.Write(xml);
  1. Xml轉(zhuǎn)換到List
List<Student> list2 = XmlUtil.Deserialize(typeof(List<Student>), xml)as List<Student>;
foreach(Student stu inlist2)
{
    Console.WriteLine(stu.Name +"," + stu.Age.ToString());
}

從代碼可以看到上沐,千變?nèi)f化不離其宗!

.Net Framework提供了對(duì)應(yīng)的System.Xml.Seriazliation.XmlSerializer負(fù)責(zé)把對(duì)象序列化到XML皮服,和從XML中反序列化為對(duì)象。Serializer的使用比較直觀参咙,需要多注意的是XML序列化相關(guān)的Attribute冰更,怎么把這些attribute應(yīng)用到我們的對(duì)象,以及對(duì)象公共屬性上面去昂勒,生成滿足預(yù)期格式的XML蜀细。
本文列出了最常用的方法和特性,涵蓋日常大部分的轉(zhuǎn)換工作戈盈,希望大家在工作中快速上手奠衔。為了給大家直觀的印象,這里給出具體的使用代碼塘娶,為了節(jié)省篇幅归斤,代碼異常處理沒有添加,各位同學(xué)使用的時(shí)候酌情添加刁岸。

1. Serializer方法

下面的方法封裝了XmlSerializer的調(diào)用脏里,這里列出了參數(shù)最全的一個(gè)版本,具體使用的時(shí)候需適當(dāng)添加重載:

public static class XmlSerializer
    {
        public static void SaveToXml(string filePath, object sourceObj, Type type, string xmlRootName)
        {
            if (!string.IsNullOrWhiteSpace(filePath) && sourceObj != null)
            {
                type = type != null ? type : sourceObj.GetType();

                using (StreamWriter writer = new StreamWriter(filePath))
                {
                    System.Xml.Serialization.XmlSerializer xmlSerializer = string.IsNullOrWhiteSpace(xmlRootName) ?
                        new System.Xml.Serialization.XmlSerializer(type) :
                        new System.Xml.Serialization.XmlSerializer(type, new XmlRootAttribute(xmlRootName));
                    xmlSerializer.Serialize(writer, sourceObj);
                }
            }
        }

        public static object LoadFromXml(string filePath, Type type)
        {
            object result = null;

            if (File.Exists(filePath))
            {
                using (StreamReader reader = new StreamReader(filePath))
                {
                    System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(type);
                    result = xmlSerializer.Deserialize(reader);
                }
            }

            return result;
        }
    }
2. 序列化常用Attribute講解說明:

[XmlRootAttribute("MyCity", Namespace="abc.abc", IsNullable=false)] // 當(dāng)該類為Xml根節(jié)點(diǎn)時(shí)虹曙,以此為根節(jié)點(diǎn)名稱迫横。
public class City

[XmlAttribute("AreaName")] // 表現(xiàn)為Xml節(jié)點(diǎn)屬性。<... AreaName="..."/>
public string Name

[XmlElementAttribute("AreaId", IsNullable = false)] // 表現(xiàn)為Xml節(jié)點(diǎn)酝碳。<AreaId>...</AreaId>
public string Id

[XmlArrayAttribute("Areas")] // 表現(xiàn)為Xml層次結(jié)構(gòu)矾踱,根為Areas,其所屬的每個(gè)該集合節(jié)點(diǎn)元素名為類名疏哗。<Areas><Area ... /><Area ... /></Areas>
public Area[] Areas

[XmlElementAttribute("Area", IsNullable = false)] // 表現(xiàn)為水平結(jié)構(gòu)的Xml節(jié)點(diǎn)呛讲。<Area ... /><Area ... />...
public Area[] Areas

[XmlIgnoreAttribute] // 忽略該元素的序列化。

3. 詳細(xì)舉例說明

這里用簡(jiǎn)單的城市,區(qū)域和街區(qū)作為例子贝搁,具體示范一下上面的規(guī)則吗氏。

[XmlRootAttribute("MyCity", Namespace = "abc.abc", IsNullable = false)]
    public class City
    {
        [XmlAttribute("CityName")] 
        public string Name
        {
            get;
            set;
        }

        [XmlAttribute("CityId")] 
        public string Id
        {
            get;
            set;
        }

        [XmlArrayAttribute("Areas")]
        public Area[] Areas
        {
            get;
            set;
        }
    }

    [XmlRootAttribute("MyArea")]
    public class Area
    {
        [XmlAttribute("AreaName")] 
        public string Name
        {
            get;
            set;
        }

        [XmlElementAttribute("AreaId", IsNullable = false)]
        public string Id
        {
            get;
            set;
        }

        [XmlElementAttribute("Street", IsNullable = false)]
        public string[] Streets
        {
            get;
            set;
        }
    }

根據(jù)以上類型,我們mock一些數(shù)據(jù)雷逆,然后用步驟1給出的Util方法輸出:

static void Main(string[] args)
    {
        Area area1 = new Area();
        area1.Name = "Pudong";
        area1.Id = "PD001";
        area1.Streets = new string [] { "street 001", "street 002" };
        Area area2 = new Area();
        area2.Name = "Xuhui";
        area2.Id = "XH002";
        area2.Streets = new string [] { "street 003", "street 004" };

        City city1 = new City();
        city1.Name = "Shanghai";
        city1.Id = "SH001";
        city1.Areas = new Area[] { area1, area2 };

        XmlSerializer.SaveToXml(@"C:\temp\XML\output003.xml", city1);
    }

最終輸出的XML為:

<?xml version="1.0" encoding="utf-8"?>
<MyCity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        CityName="Shanghai" CityId="SH001" xmlns="abc.abc">
  <Areas>
    <Area AreaName="Pudong">
      <AreaId>PD001</AreaId>
      <Street>street 001</Street>
      <Street>street 002</Street>
    </Area>
    <Area AreaName="Xuhui">
      <AreaId>XH002</AreaId>
      <Street>street 003</Street>
      <Street>street 004</Street>
    </Area>
  </Areas>
</MyCity>

下面我們開始具體分析結(jié)果弦讽,其中包含一些很有用的結(jié)論和注意事項(xiàng):

  1. xml的版本,編碼关面,以及命名空間xmlns:xsi坦袍,xmlns:xsd為Framework自動(dòng)添加十厢。

  2. 因?yàn)槲覀冇肅ity對(duì)象作為根節(jié)點(diǎn)等太,所以根節(jié)點(diǎn)名稱為我們定義的"MyCity"。
    但是蛮放,注意缩抡!這里指的是用City自身直接做根節(jié)點(diǎn),如果是City集合比如City[]包颁,此時(shí)瞻想,該名稱失效,系統(tǒng)會(huì)自動(dòng)生成名稱ArrayOfCity作為根節(jié)點(diǎn)名稱(ArrayOf+類名)娩嚼,或者我們手動(dòng)指定名稱蘑险,這個(gè)就是在給大家的SaveToXml()方法中,參數(shù)xmlRootName的作用岳悟。

  3. 如果以City為根節(jié)點(diǎn)并在XmlRootAttribute特性中給定名稱佃迄,同時(shí)也手動(dòng)指定了xmlRootName,系統(tǒng)會(huì)以手動(dòng)指定的名稱為準(zhǔn)贵少。

  4. AreaName呵俏,AreaId,同為Area類的公共屬性滔灶,一個(gè)被解釋成屬性普碎,一個(gè)被解釋成子節(jié)點(diǎn)。
    Areas集合被解釋成了層次結(jié)構(gòu)录平,Streets集合被解釋成了水平結(jié)構(gòu)麻车。
    這兩組區(qū)別最能體現(xiàn)不同序列化Attribute的用法。

4. 結(jié)語(yǔ)

這里用例子說明了Xml Serializer的用法斗这,C#類和Xml之間的結(jié)構(gòu)映射绪氛,希望足夠同學(xué)們對(duì)付日常工作。更深入的討論會(huì)在后續(xù)的文章跟進(jìn)涝影。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末枣察,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌序目,老刑警劉巖臂痕,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異猿涨,居然都是意外死亡握童,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門叛赚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澡绩,“玉大人,你說我怎么就攤上這事俺附》士ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵事镣,是天一觀的道長(zhǎng)步鉴。 經(jīng)常有香客問我,道長(zhǎng)璃哟,這世上最難降的妖魔是什么氛琢? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮随闪,結(jié)果婚禮上阳似,老公的妹妹穿的比我還像新娘。我一直安慰自己铐伴,他們只是感情好撮奏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盛杰,像睡著了一般挽荡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上即供,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天定拟,我揣著相機(jī)與錄音,去河邊找鬼逗嫡。 笑死青自,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驱证。 我是一名探鬼主播延窜,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼抹锄!你這毒婦竟也來了逆瑞?” 一聲冷哼從身側(cè)響起荠藤,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎获高,沒想到半個(gè)月后哈肖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡念秧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年淤井,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摊趾。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡币狠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砾层,到底是詐尸還是另有隱情漩绵,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布梢为,位于F島的核電站渐行,受9級(jí)特大地震影響轰坊,放射性物質(zhì)發(fā)生泄漏铸董。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一肴沫、第九天 我趴在偏房一處隱蔽的房頂上張望粟害。 院中可真熱鬧,春花似錦颤芬、人聲如沸悲幅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)汰具。三九已至,卻和暖如春菱魔,著一層夾襖步出監(jiān)牢的瞬間留荔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工澜倦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聚蝶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓藻治,卻偏偏與公主長(zhǎng)得像碘勉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桩卵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容