很多時候,我們開發程序都需要使用到對象的XML序列化和反序列化,對象的XML序列化和反序列化,既可以使用XML對象(XmlDocument )進行操作,也可以使用XmlSerializer進行操作,兩個各有優點,就操作性而已,我傾向於使用后者來操作XML。本文介紹三種方式操作XML,普通的XDocument的API操作,方便的XmlSerializer對象序列化及反序列化操作,加密XML對象序列化操作。
1、普通的XML對象操作,利用XML對象(XmlDocument )。
一個典型的利用XmlDocument對象操作XML的例子代碼如下。
public static void RunSnippet() { XmlDocument xmldoc = new XmlDocument ( ) ; //加入XML的聲明段落 XmlNode xmlnode = xmldoc.CreateNode ( XmlNodeType.XmlDeclaration , "" , "" ) ; xmldoc.AppendChild (xmlnode ) ; //加入一個根元素 XmlElement xmlelem = xmldoc.CreateElement ( "" , "ROOT" , "" ) ; XmlText xmltext = xmldoc.CreateTextNode ( "Root Text" ) ; xmlelem.AppendChild ( xmltext ) ; xmldoc.AppendChild ( xmlelem ) ; //加入另外一個元素 XmlElement xmlelem2 = xmldoc.CreateElement ("SampleElement" ) ; xmlelem2 = xmldoc.CreateElement ( "" , "SampleElement" , "" ) ; xmltext = xmldoc.CreateTextNode ( "The text of the sample element" ) ; xmlelem2.AppendChild ( xmltext ) ; xmldoc.ChildNodes.Item(1).AppendChild ( xmlelem2 ) ; //保存創建好的XML文檔 try { xmldoc.Save ( "c:\\data.xml" ) ; } catch ( Exception e ) { //顯示錯誤信息 Console.WriteLine ( e.Message ) ; } Console.ReadLine ( ) ; }
得到的輸出結果如下所示。
<?xml version="1.0"?> <ROOT>Root Text <SampleElement>The text of the sample element</SampleElement> </ROOT>
2、使用XmlSerializer進行XML操作
先提供兩個對象的序列化和反序列化的封裝函數,如下所示。
/// <summary> /// 對象序列化XML到文件中 /// </summary> /// <param name="path">文件路徑</param> /// <param name="obj">對象</param> /// <param name="type">對象類型</param> private bool XmlSerialize(string path, object obj, Type type) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); try { //如果文件目錄不存在,那么創建目錄 if (!File.Exists(path)) { FileInfo fi = new FileInfo(path); if (!fi.Directory.Exists) { Directory.CreateDirectory(fi.Directory.FullName); } } using (Stream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { XmlSerializer format = new XmlSerializer(type); format.Serialize(stream, obj, ns); stream.Close(); } return true; } catch (Exception ex) { Console.WriteLine(ex.Message); return false; } } /// <summary> /// XML反序列化 /// </summary> /// <param name="path">文件路徑</param> /// <param name="type">對象類型</param> /// <returns></returns> private object XmlDeserialize(string path, Type type) { try { using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { XmlSerializer formatter = new XmlSerializer(type); stream.Seek(0, SeekOrigin.Begin); object obj = formatter.Deserialize(stream); stream.Close(); return obj; } } catch { return null; } }
注意其中代碼
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
是把默認的xmlns命名空間多余的內容去掉,這樣得到比較干凈的XML。
在使用的時候,我們需要定義好對象的實體,這樣才能給予對象進行操作,定義的實體類如下所示。
[Serializable] public class UserInfo { public string ID { get; set; } public string UserNo{ get; set; } public string UserName { get; set; } public string Sex { get; set; } public string Birthday { get; set; } } [Serializable] public class DataOfUser { [XmlElement(ElementName = "m_User")] public List<UserInfo> list = new List<UserInfo>(); }
調用序列化函數的代碼例子如下所示
private void btnUserNormal_Click(object sender, EventArgs e) { DataOfUser obj = new DataOfUser(); UserInfo user = new UserInfo(); user.ID=Guid.NewGuid().ToString(); user.Sex = "男"; user.UserName = "張三"; user.UserNo = "20010001"; user.Birthday = "1999-1-1"; obj.list.Add(user); user = new UserInfo(); user.ID = Guid.NewGuid().ToString(); user.Sex = "女"; user.UserName = "李氏"; user.UserNo = "20020001"; user.Birthday = "1998-1-1"; obj.list.Add(user); try { XmlSerialize("C:\\User.xml", obj, obj.GetType()); MessageUtil.ShowTips("Ok"); } catch (Exception ex) { MessageUtil.ShowError(ex.Message); } }
這樣得到的XML內容如下所示。
<?xml version="1.0"?> <DataOfUser> <m_User> <ID>f8a8b323-5c56-4c21-9ddf-1cd30f78dfca</ID> <UserNo>20010001</UserNo> <UserName>張三</UserName> <Sex>男</Sex> <Birthday>1999-1-1</Birthday> </m_User> <m_User> <ID>bbb36378-ec27-4e20-ad4b-2d2dc7e142e4</ID> <UserNo>20020001</UserNo> <UserName>李氏</UserName> <Sex>女</Sex> <Birthday>1998-1-1</Birthday> </m_User> </DataOfUser>
反序列化的操作也比較簡單,不再贅述。
3)把對象實例化到XML中並進行加密處理
首先我們定義兩個序列化加密、解碼並反序列化的函數如下所示。
/// <summary> /// XML序列化並加密 /// </summary> /// <param name="path">文件路徑</param> /// <param name="obj">對象</param> /// <param name="type">對象類型</param> /// <returns></returns> private bool XmlSerializeEncrypt(string path, object obj, Type type) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); try { if (!File.Exists(path)) { FileInfo fi = new FileInfo(path); if (!fi.Directory.Exists) { Directory.CreateDirectory(fi.Directory.FullName); } } using (Stream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { string content = ""; using(MemoryStream ms = new MemoryStream()) { XmlSerializer format = new XmlSerializer(type); format.Serialize(ms, obj, ns); ms.Seek(0, 0); content = Encoding.UTF8.GetString(ms.ToArray()); } string encrypt = EncodeHelper.EncryptString(content); byte[] bytes = Encoding.UTF8.GetBytes(encrypt); stream.Write(bytes, 0, bytes.Length); stream.Close(); } return true; } catch (Exception ex) { Console.WriteLine(ex.Message); return false; } } /// <summary> /// 解密並進行XML反序列化 /// </summary> /// <param name="path">文件路徑</param> /// <param name="type">對象類型</param> /// <returns></returns> private object XmlDeserializeDecrypt(string path, Type type) { try { string encrypt = File.ReadAllText(path, Encoding.UTF8); string content = EncodeHelper.DecryptString(encrypt, true); byte[] bytes = Encoding.UTF8.GetBytes(content); using (MemoryStream stream = new MemoryStream(bytes)) { XmlSerializer formatter = new XmlSerializer(type); stream.Seek(0, SeekOrigin.Begin); object obj = formatter.Deserialize(stream); stream.Close(); return obj; } } catch(Exception ex) { Console.WriteLine(ex.Message); return null; } }
這樣函數定義好后,調用和前面沒有加密的差不多,如下所示。
private void btnUserEncrypt_Click(object sender, EventArgs e) { DataOfUser obj = new DataOfUser(); UserInfo user = new UserInfo(); user.ID = Guid.NewGuid().ToString(); user.Sex = "男"; user.UserName = "張三"; user.UserNo = "20010001"; user.Birthday = "1999-1-1"; obj.list.Add(user); user = new UserInfo(); user.ID = Guid.NewGuid().ToString(); user.Sex = "女"; user.UserName = "李氏"; user.UserNo = "20020001"; user.Birthday = "1998-1-1"; obj.list.Add(user); try { XmlSerializeEncrypt("C:\\User-Encrypt.xml", obj, obj.GetType()); MessageUtil.ShowTips("Ok"); } catch (Exception ex) { MessageUtil.ShowError(ex.Message); } } private void btnUserDecrypt_Click(object sender, EventArgs e) { string file = FileDialogHelper.OpenFile(); if (!string.IsNullOrEmpty(file)) { DataOfUser info = XmlDeserializeDecrypt(file, typeof(DataOfUser)) as DataOfUser; if (info != null) { MessageUtil.ShowTips("OK"); } } }