[转载]关于XML与类型Class的映射 - 凤城居士 - 博客园

[转载]关于XML与类型Class的映射 – 凤城居士 – 博客园.

我们知道数据的持久化是编程必须面对的问题。我们可以保存数据到数据库、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属性。

接下来就是反序列化了

View Code

 

生成的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 晚

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏