我们知道数据的持久化是编程必须面对的问题。我们可以保存数据到数据库、Excel表、XML文件、TXT文件等等。那么我们编程中经常会遇到对Xml文件的操作。在http://www.cnblogs.com/fengchengjushi/p/3266191.html这里我已经简单总结了传统的Xml文件操作办法。也引出了对Xml文件和类型Class之间可以进行映射,从而简化操作,提高效率。那么,很多时候我们并不一定能自己定义好相应的映射Class。比方说,对业已存在的Xml文件的操作。那么,我们就需要看Xml文件的节点构成,然后反向由Xml文件映射出需要的Class。接下来,我就以demo为例。
XmlHelper帮助类
public class XmlHelper { #region XML序列化 /// <summary> /// 文件化XML序列化 /// </summary> /// <param name="obj">对象</param> /// <param name="filename">文件路径</param> public static void Save(object obj, string filename) { FileStream fs = null; try { fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); XmlSerializer serializer = new XmlSerializer(obj.GetType()); serializer.Serialize(fs, obj); } catch (Exception ex) { throw ex; } finally { if (fs != null) fs.Close(); } } /// <summary> /// 文件化XML反序列化 /// </summary> /// <param name="type">对象类型</param> /// <param name="filename">文件路径</param> public static object Load(Type type, string filename) { FileStream fs = null; try { fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); XmlSerializer serializer = new XmlSerializer(type); return serializer.Deserialize(fs); } catch (Exception ex) { throw ex; } finally { if (fs != null) fs.Close(); } } #endregion }
Test.xml文件
<?xml version="1.0" encoding="utf-8" ?> <RuleSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Gateway Code="AAA"> <Rules> <Rule Code="202" OrderID="1" IsMustExecute="true"> <Settings> <Setting Key="ClassDays_30d" Value="1000" /> </Settings> </Rule> <Rule Code="301" OrderID="2" IsMustExecute="true"> <Settings> <Setting Key="GameRole" Value="true" /> </Settings> </Rule> </Rules> </Gateway> <!--PayPalCreditCard--> <Gateway Code="BBB"> <Rules> <Rule Code="100" OrderID="1" IsMustExecute="true"> </Rule> <Rule Code="201" OrderID="2" IsMustExecute="true"> <Settings> <Setting Key="SumOrderAmount_7d" Value="500" /> </Settings> </Rule> <Rule Code="800" OrderID="23" IsMustExecute="true"> <Settings> <Setting Key="High1" Value="-60" /> <Setting Key="High2" Value="-30" /> <Setting Key="High3" Value="-10" /> </Settings> </Rule> </Rules> </Gateway> </RuleSettings>
我们来看这个文件,它的整体结构如下:根节点RuleSettings,它包含Gateway节点的集合。Gateway节点又包含Rules(单个)节点,Rules节点又包含Rule节点集合,Rule节点下面包含单个Settings(为了讲讲它的特别之处,下面我们对它采取异于Rules节点的处理方法)节点,这之下包含多个Setting节点。而且,Settings节点可以没有。
现在开始映射对应的Class类型。一个节点实际上是一个XmlElement 也对应一个Class,属性即XmlAttribute就对Class的属性,如果该节点有InnerText就在定义的属性上加XmlText。那么我们对应出如下类型
public class RuleSettings { public List<Gateway> Gateway { get; set; } } public class Gateway { [XmlAttribute("Code")] public string Code { get; set; } public List<Rule> Rules { get; set; } } public class Rule { [XmlAttribute("Code")] public string Code { get; set; } [XmlAttribute("OrderID")] public string OrderID { get; set; } [XmlAttribute("IsMustExecute")] public bool IsMustExecute { get; set; } //[XmlAttribute("Settings")] [XmlElement("Settings")] public Settings Settings { get; set; } } /// <summary> /// 注:对于这种无XmlAttribute的节点。且它包含子节点。我们这样做时 /// 必须给Settinghe上面的Settings标明是XmlElment /// 不然会多出一个Setting节点 /// 或者直接在上面使用public List<Setting> Settings { get; set; } /// 省去Settings类 /// </summary> public class Settings { [XmlElement("Setting")] public List<Setting> Setting { get; set; } } public class Setting { [XmlAttribute("key")] public string key { get; set; } [XmlAttribute("value")] public string value { get; set; } }
其中Rules和Settings节点就是无任何属性,且包含子节点集合的节点。对于Rules我们不考虑映射一个Class,采取在Gateway节点下面直接定义Rule集合Rules。同时设置它的节点名称为Settings。对于Settings我们同样定义一个类型。它里面有一个属性是Setting节点的集合。此时。我们必须在Rule类型下的Settings加上XmlElement属性。
接下来就是反序列化了
RuleSettings rs = new RuleSettings { Gateway = new List<Gateway>() { new Gateway() { Code="AAA", Rules=new List<Rule>() { new Rule() { Code="201", IsMustExecute=true, OrderID="1", Settings=new Settings { Setting=new List<Setting>() { new Setting{key="ClassDays_30d",value="12"}, new Setting{key="GameRole",value="true"} }, }, }, new Rule() { Code="301", IsMustExecute=true, OrderID="2", Settings=new Settings { Setting=new List<Setting>() { new Setting{key="GameRole",value="true"} }, }, }, }, }, new Gateway() { Code="BBB", Rules=new List<Rule>() { new Rule() { Code="100", IsMustExecute=true, OrderID="1", Settings=null }, new Rule() { Code="201", IsMustExecute=true, OrderID="2", Settings=new Settings { Setting=new List<Setting>() { new Setting{key="SumOrderAmount_7d",value="600"} }, }, }, new Rule() { Code="800", IsMustExecute=true, OrderID="23", Settings=new Settings { Setting=new List<Setting>() { new Setting{key="High1",value="60"}, new Setting{key="High2",value="10"}, new Setting{key="High3",value="10"} }, }, }, }, } }, }; XmlHelper.Save(rs, Server.MapPath("Xml//RuleSetting.xml"));
生成的RuleSetting.xml文件如下
<?xml version="1.0"?> <RuleSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Gateway> <Gateway Code="AAA"> <Rules> <Rule Code="201" OrderID="1" IsMustExecute="true"> <Settings> <Setting> <Setting key="ClassDays_30d" value="12" /> <Setting key="GameRole" value="true" /> </Setting> </Settings> </Rule> <Rule Code="301" OrderID="2" IsMustExecute="true"> <Settings> <Setting> <Setting key="GameRole" value="true" /> </Setting> </Settings> </Rule> </Rules> </Gateway> <Gateway Code="BBB"> <Rules> <Rule Code="100" OrderID="1" IsMustExecute="true" /> <Rule Code="201" OrderID="2" IsMustExecute="true"> <Settings> <Setting> <Setting key="SumOrderAmount_7d" value="600" /> </Setting> </Settings> </Rule> <Rule Code="800" OrderID="23" IsMustExecute="true"> <Settings> <Setting> <Setting key="High1" value="60" /> <Setting key="High2" value="10" /> <Setting key="High3" value="10" /> </Setting> </Settings> </Rule> </Rules> </Gateway> </Gateway> </RuleSettings>
对于根节点 RuleSettings可以加上
[XmlRoot(Namespace = "http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd")]
其实上面处理一个节点下有多个字节点的集合时我们可以采用数组。当然个人习惯。可以自己试试,效果是一样的。
就写到这儿,此处受http://www.cnblogs.com/fish-li/的文章影响,它介绍很细致,你们可以看下。总感觉看了,就想自己写,理解得更透彻点。
2013-10-14 晚