1. 程式人生 > >C#中使用DataContractSerializer反序列化多級xml

C#中使用DataContractSerializer反序列化多級xml

DataContractSerializer類可以將型別例項序列化成xml或者將xml反序列化為型別例項,具體細節可以參照MSDN官方文件
最近遇到了使用DataContractSerializer反序列化多級xml檔案為物件的問題,這裡的多級指的是xml檔案中的節點深度大於2,檔案結構如下:
<StudentInfo>
  <Name>Kevin</Name>
  <Age>23</Age>
  <GirlFriend>
    <Name>Waner</Name>
    <Location>Sydney</Location>
  </GirlFriend>
</StudentInfo>
可以看到,這裡的節點深度為3,節點深度比較低的序列化和反序列化方法msdn範例已經給出。
首先我們新建一個Student類,用於存放xml檔案中所有節點資訊,如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace DeserializeXml
{
    /// <summary>
    /// Student information from xml file
    /// </summary>
    [DataContract(Name = "StudentInfo",Namespace = "")]
    public class Student
    {
        #region properties

        [DataMember(Name = "Name", Order = 1)]
        public string Name { get; set; }

        [DataMember(Name = "Age", Order = 2)]
        public string Age { get; set; }

        [DataMember(Name = "GirlFriend", Order = 3)]
        public GirlFriend GirlFriend { get; set; }
        #endregion

        #region public methods

        public void PrintInfo()
        {
            if (GirlFriend != null)
            {
                Console.WriteLine("{0} is {1} years old, and his girlfriend is {2}, who is in {3} now.", Name, Age, GirlFriend.Name, GirlFriend.Location);
            }
            else if (!string.IsNullOrEmpty(Name))
            {
                Console.WriteLine("Sorry, {0}'s world is empty.", Name);
            }
            else
            {
                Console.WriteLine("Nothing to be printed.");
            }
        }

        #endregion
    }

    /// <summary>
    /// Girlfriend information from xml file.
    /// </summary>
    [DataContract(Name = "GirlFriend", Namespace = "")]
    public class GirlFriend
    {
        #region properties

        [DataMember(Name = "Name", Order = 1)]
        public string Name { get; set; }

        [DataMember(Name = "Location", Order = 2)]
        public string Location { get; set; }

        #endregion
    }
}

這裡需要注意幾點:

1、Student類前被標記了DataContract Attribute,其Name值要和xml文件的根節點相對應。Student類中每個屬性前被標記了DataMember Attribute,其Name值要和每個節點的名稱相對應。

2、由於GirlFriend節點下有子節點,所以需要新建類GirlFriend,用於儲存GirlFriend下的節點,其標記方式和Student類相似。

3、DataMember Attribute中有個屬性叫Order,該屬性代表所對應節點在xml文件中出現的順序,Order=1即代表該節點是在當前深度中的第一個節點,依次類推。

接下來新增類DeserializeXml類,實現反序列化xml文件的具體操作,細節如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace DeserializeXml
{
    public class DeserializeXml
    {
        #region constructor

        public DeserializeXml(string filePath)
        {
            FilePath = filePath;
        }

        #endregion

        #region properties

        public string FilePath
        {
            get;
            set;
        }

        #endregion

        #region public methods

        public void DeserializeFromXml()
        {
            try
            {
                FileStream fs = new FileStream(FilePath,FileMode.Open);
                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, XmlDictionaryReaderQuotas.Max);
                DataContractSerializer ser = new DataContractSerializer(typeof(Student));
                Student student = (Student)ser.ReadObject(reader, true);
                student.PrintInfo();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        #endregion
    }

最後在Program類中進行簡單呼叫即可(最後為專案結構圖)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeserializeXml
{
    class Program
    {
        static void Main(string[] args)
        {

            DeserializeXml deserializeXml = new DeserializeXml("../../Student.xml");
            deserializeXml.DeserializeFromXml();
            Console.ReadKey();
        }
    }
}