XML序列化和反序列化

上篇總結了下JSON的序列化和反序列化,博園中大牛給了不少牛叉的評論,學習了很多。html

不過在上篇中忘了把json序列化和反序列化的另一種方式寫上去了,這裏作個簡單的補充:json

Json篇:http://www.cnblogs.com/zhanghaomars/p/3557644.html工具

Json序列化和反序列化擴展方法實現類:學習

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

namespace HelpClass.TypeHelp
{
    public static class JsonHelpExpand
    {
        public static string JsonSerializer<T>(this T t) where T : class
        {
            JavaScriptSerializer jsonSerialize = new JavaScriptSerializer();
            return jsonSerialize.Serialize(t);
        }

        public static T JsonDeserialize<T>(this string jsonString)
        {
            JavaScriptSerializer jsonSerialize = new JavaScriptSerializer();
            return (T)jsonSerialize.Deserialize<T>(jsonString);
        }
    }
}

Ok!接下來就是XMLthis

 

一、  靜態方法+泛型實現編碼

XML工具類:spa

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace HelpClass.TypeHelp
{
    public class XMLHelp
    {
        private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding, bool isnamespaces)
        {
            if (o == null)
                throw new ArgumentNullException("o");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            XmlSerializer serializer = new XmlSerializer(o.GetType());

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineChars = "\r\n";
            settings.Encoding = encoding;
            settings.IndentChars = "    ";

            //不生成聲明頭
            settings.OmitXmlDeclaration = !isnamespaces;

            MemoryStream w = new MemoryStream();

            XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
            namespaces.Add("", "");

            using (XmlWriter writer = XmlWriter.Create(stream, settings))
            {
                serializer.Serialize(writer, o, namespaces);
                writer.Close();

            }
        }

        /// <summary>
        /// 將一個對象序列化爲XML字符串
        /// </summary>
        /// <param name="o">要序列化的對象</param>
        /// <param name="encoding">編碼方式</param>
        /// <param name="isnamespaces">是否須要命名空間true:須要 false:不須要</param>
        /// <returns>序列化產生的XML字符串</returns>
        public static string XmlSerialize(object o, Encoding encoding, bool isnamespaces)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                XmlSerializeInternal(stream, o, encoding, isnamespaces);

                stream.Position = 0;
                using (StreamReader reader = new StreamReader(stream, encoding))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// 從XML字符串中反序列化對象
        /// </summary>
        /// <typeparam name="T">結果對象類型</typeparam>
        /// <param name="s">包含對象的XML字符串</param>
        /// <param name="encoding">編碼方式</param>
        /// <returns>反序列化獲得的對象</returns>
        public static T XmlDeserialize<T>(string s, Encoding encoding)
        {
            if (string.IsNullOrEmpty(s))
                throw new ArgumentNullException("s");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            XmlSerializer mySerializer = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream(encoding.GetBytes(s)))
            {
                using (StreamReader sr = new StreamReader(ms, encoding))
                {
                    return (T)mySerializer.Deserialize(sr);
                }
            }
        }

        /// <summary>
        /// 將一個對象按XML序列化的方式寫入到一個文件
        /// </summary>
        /// <param name="o">要序列化的對象</param>
        /// <param name="path">保存文件路徑</param>
        /// <param name="encoding">編碼方式</param>
        /// <param name="isnamespaces">是否須要命名空間true:須要 false:不須要</param>
        public static void XmlSerializeToFile(object o, string path, Encoding encoding, bool isnamespaces)
        {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");

            using (FileStream file = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                XmlSerializeInternal(file, o, encoding,isnamespaces);
            }
        }

        /// <summary>
        /// 讀入一個文件,並按XML的方式反序列化對象。
        /// </summary>
        /// <typeparam name="T">結果對象類型</typeparam>
        /// <param name="path">文件路徑</param>
        /// <param name="encoding">編碼方式</param>
        /// <returns>反序列化獲得的對象</returns>
        public static T XmlDeserializeFromFile<T>(string path, Encoding encoding)
        {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            string xml = File.ReadAllText(path, encoding);
            return XmlDeserialize<T>(xml, encoding);
        }
    }
}

在一個項目中,若是面臨大量的XML(如調用大量返回XML的外部接口),這時就須要根據XML結構來逆向推導C#類型,而後才能使用序列化和反序列化的方法。code

當須要根據XML結構逆向推導類型,咱們須要瞭解一下類型定義與XML結構的映射關係。xml

映射關係只須要記住幾個標籤:htm

(1)       [XmlElement]

類中的屬性或者字段在不標記下默認都會生成XmlElement(不加任何Attribute的狀況下)該標籤把類中的屬性或者字段序列化爲XML中的節點

Public class ddd

{

         [XmlElement]

         Public string d1{get;set;}

         Public string d2{get;set;}

 

}

ddd cd=new ddd{d1=」1」,d2=」2」}

<ddd><d1>1</d1><d2>2</d2></ddd>

(2)       [XmlAttribute]

類中的屬性或者字段在標記爲[XmlAttribute]的狀況下會生成爲XML中以以該類名爲節點的屬性

Public class ddd

{

         [XmlAttribute]

         Public string d1{get;set;}

         [XmlElement]

         Public string d2{get;set;}

 

}

ddd cd=new ddd{d1=」1」,d2=」2」}

<ddd d1=」1」><d2>2</d2></ddd>

(3)       [InnerText]

若是但願類型中的屬性或者字段生成InnerText,須要在類型的成員上用[XmlText]

Public class ddd

{

         [XmlAttribute]

         Public string d1{get;set;}

         [InnerText]

         Public string d2{get;set;}

}

ddd cd=new ddd{d1=」1」,d2=」2」}

<ddd d1=」1」>2</ddd>

(4)       重命名

XmlAttribute,XmlElement容許接受一個別名用來控制生成節點的名稱,類型的重命名用XmlType來實現

[XmlType(「ccc」)]

Public class ddd

{

         [XmlAttribute(「c1」)]

         Public string d1{get;set;}

         [XmlElement(「c2」)]

         Public string d2{get;set;}

}

ddd cd=new ddd{d1=」1」,d2=」2」}

<ccc c1=」1」><c2>2</c2></ccc>

(5)       序列化去掉XML命名空間及聲明頭(工具類中代碼以有相關說明了)

 

注意:

(1)       當須要考慮使用XML時,先不要想着XML結構,先應該定義好數據類型。

(2)       列表節點不要使用[XmlElement],它會讓全部子節點【升級】,顯得結構混亂。

(3)       若是但願序列化的XML長度小一點,能夠採用[XmlAttribute],或者指定一個更短小的別名(序列化爲JSON進行傳輸也是一種選擇)

(4)       不要在一個列表中輸出不一樣的數據類型,這樣的XML結構的可讀性很差。

(5)       儘可能使用UTF-8編碼,不要使用GB2312編碼。

(6)       列表節點不要使用[XmlElement],它會讓全部子節點【升級】,顯得結構混亂。

二、  擴展方法+泛型實現

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace HelpClass.TypeHelp
{
    public static class XMLHelpExpand
    {
        /// <summary>
        /// XML序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="o"></param>
        /// <param name="isnamespaces">是否須要命名空間true:須要 false:不須要</param>
        /// <returns></returns>
        public static string XmlSerializer<T>(this T o,bool isnamespaces)where T:class
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(o.GetType());

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineChars = "\r\n";
            settings.Encoding = Encoding.UTF8;
            settings.IndentChars = "   ";

            //不生成聲明頭
            settings.OmitXmlDeclaration = !isnamespaces;

            MemoryStream w = new MemoryStream();

            XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
            namespaces.Add("", "");

            using (XmlWriter writer = XmlWriter.Create(w, settings))
            {
                serializer.Serialize(writer, o, namespaces);
                writer.Close();
            }

            return Encoding.UTF8.GetString(w.ToArray());
        }

        /// <summary>
        /// XML反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="XmlString"></param>
        /// <returns></returns>
        public static T XmlDeserialize<T>(this string XmlString)
        {
            if (string.IsNullOrEmpty(XmlString))
                throw new ArgumentNullException("s");

            XmlSerializer mySerializer = new XmlSerializer(typeof(T));

            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XmlString)))
            {
                using (StreamReader sr = new StreamReader(ms, Encoding.UTF8))
                {
                    return (T)mySerializer.Deserialize(sr);
                }
            }
        }
    }
}

看完了上面的這些或許你已經對XML的序列化和反序列化有了必定的瞭解,今天就寫到這裏,下次總結一下別的。

相關文章
相關標籤/搜索