XML序列化和反序列化


上篇總結了下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!接下來就是XML

 

1、  靜態方法+泛型實現

XML工具類:

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#類型,然后才能使用序列化和反序列化的方法。

當需要根據XML結構逆向推導類型,我們需要了解一下類型定義與XML結構的映射關系。

映射關系只需要記住幾個標簽:

(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],它會讓所有子節點【升級】,顯得結構混亂。

2、  擴展方法+泛型實現

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的序列化和反序列化有了一定的了解,今天就寫到這里,下次總結一下別的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM