知识大全 通过XML模板替换实现对象的灵活序列化

Posted

篇首语:书犹药也,善读可以医愚。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 通过XML模板替换实现对象的灵活序列化相关的知识,希望对你有一定的参考价值。

通过XML模板替换实现对象的灵活序列化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  前阵子在写LINQ Douban的时候碰到关于XML序列化的场景 通过Douban api添加和更新数据的时候都需要Post一个xml entry 如

  添加活动(xml中用%%括起来的部分是需要填写的部分 为了精简删除了xmlns)

  view sourceprint? <?xml version= encoding= UTF ?>

   <entry>

      <title>%title%</title>

      <category scheme= term= ;

      <content>%Content%</content>

  

      <db:attribute name= invite_only >%IsInviteOnly%</db:attribute>

      <db:attribute name= can_invite >%CanInvite%</db:attribute>

      <gd:when endTime= %Duration End% startTime= %Duration Start% />

      <gd:where valueString= %Where% />

   </entry>

  一下子能想到的方法有两个——通过XmlSerializer或在entity class上实现IXmlSerializable接口来实现 但很快发现有几个问题没法解决

   XmlSerializer不支持泛型集合的序列化 而我在定义entity class时用了不少IList和IDictionary 如db:attribute我就定义成IDictionary

   XmlSerializer只能生成完整的element和attribute 像上面那段xml里<category>节点term属性里变化的只有后面%Category%部分 这就没法生成了

   存在添加和更新的post内容不一样的情况 这就意味着同一个entity class 存在多种序列化方案

   douban的xml entry格式可能会更改 而我不希望因此而更改代码

  想来想去 最好的方法是通过XML模板+反射(简称XMl模板替换)来生成了 就像上面的xml etnry里面%%括起来的部分 替换掉就可以了 这样可以解决上述的四个问题 除了提供和XMLSerializer功能相同的序列化之外 XML模板替换还要满足下面这些要求

   可以序列化实现IEnumerable的集合 这是最常用的集合 当然大多数的泛型集合也是应用了IEnumerable的

   提供更灵活的替换 XmlSerializer实现的序列化顺序是 A(B(c)B)A 对于子对象的序列化只能是嵌套的模式 而XML模板替换可以实现任何层次的替换

   为每种类型的对象提供通用的序列化方式 不需要任何Attribute定义 不需要修改对象的定义 对于给定的object和XML模板 通过发射获取属性值进行XML替换后生成XML内容 对于相同的object 提供不同的XML模板就能生成不同的XML

   通过修改XML模板即可修改序列化结果

  下面给出一个修改过的RSS的XML模板 这次Code Fun的目的是在最后实现这个模板的替换 并且完成一个能够实现上述功能的Helper class

  特别的地方

   <category>节点 通过 可访问子对象的属性 如果你希望获取Domain的长度可以写成 %Category Domain Length%

   <noReplacement>节点 该节点不包含任何替换信息 当进行替换处理时应当忽略

   <skipHours>节点 SkipHours是一个List<int>集合 我们希望能够根据SkipHours的值 展开多个<hour>节点

   <as:scope>节点 <scope>是模板定义 声明<scope>节点内包含的子节点在Channel Items对象的作用域中 所有%%(不包括% /Category Name%)的属性都是对Items对象的属性访问 由于此处Items对象是List<RssItem>集合 所以将循环生成多个<item> Scope的含义类似于程序域 支持多个scope的嵌套 Scope定义不会出现在最后生成的xml中

   <channelCategory>节点 <channelCategory>节点在Items的作用域中 但我们可以通过 / 访问外部scope的属性 类似dos文件路径 如果要访问上上级scope 则是 / / % /Category Name%表示访问Channel对象的Category属性的Name属性

  view sourceprint? <channel>

        <title>%Title%</title>

        <link>%Link%</link>

        <category domain= %Category Domain% >%Category Name%</category>

        <noRelacement>不需要替换</noRelacement>

        <skipHours>

          <hour>%SkinHours%</hour>

        </skipHours>

        <as:scope xmlns:as= name= Items type= AllSharing Xml Rss RssItem >

          <item>

            <title>%Title%</title>

            <link>%Link%</link>

            <description>%Description%</description>

            <channelCategory>% /Category Name%</channelCategory>

          </item>

        </as:scope>

      </channel>

  view sourceprint?

  相关class定义

  view sourceprint? public class RssChannel

  

        public string Title get; set;

            public string Link get; set;

            public RssCategory Category get; set;

            public IList<int> SkinHours get; set;

            public IList<RssItem> Items get; set;

  

  

   public class RssItem

  

            public string Title get; set;

            public string Link get; set;

  

  

   public class RssCategory

  

        public string Domain get; set;

            public string Name get; set;

  

  下面将一步步讨论如何实现XML模板的替换 会给出部分代码或伪代码 完整的代码在文章最后会给出下载

  一 分析XML模板

  XML模板替换最终要是要回归到用正则表达式替换掉所有的%% 但由于我们要处理的模板包括域 子属性访问 循环的信息 所以这不是仅仅的Regex Replace就可以搞定的 分析XML模板 就是要遍历XML模板生成一个Scope树 上面的XML模板可以生成下面的Scope树

  XML模板中包含了的三种我们需要处理的元素

   包含%%的XML Attribute

   包含%%的XML Element以及Element的子节点

   Scope节点

  从上面的Scope树可以看出 像<noReplace>这样不需要替换的XML element或XML attribute被当作常量 没有包括在Scope树中

  在Helper Class中分析Scope树的方法

  view sourceprint? var scope = XmlTemplateScope Compile(xmlPath entityType)

  xmlPath是模板文件的路径 entityType是Scope树用于分析的对象类型

  二 对给定的object 生成XML

  这里用了LINQ XML 首先用XDocument Load(xmlPath)的到XML模板文件的XDocument 然后根据Scope树对XDocument上的节点进行属性值替换 节点Value替换 增加节点(Repeat的节点) 幸运的是XDocument比XmlDocument方便太多了 实现起来非常快

  在Helper Class中生成XML的方法

  view sourceprint? var template = new XmlTemplate(xmlPath scope);

   Console WriteLine(template Translate(entityObj));

  template是线程安全的 根据需要你可以Cache起来 不用每次都生成Scope树 这样或许会减少部分性能消耗(未测试)

  完整的代码如下(包含在Demo中)

  view sourceprint? var channel = new RssChannel();

   channel Title = this is channel title ;

   channel Link = ;

   channel Description = this is channel description ;

   channel Category = new RssCategory();

   channel Category Domain = ;

   channel Category Name = this is channel category ;

   channel SkipHours Add( );

   channel SkipHours Add( );

   channel SkipHours Add( );

   channel Items Add(new RssItem Title= Item Link= Link Description= Des );

   channel Items Add(new RssItem Title = Item Link = Link Description = Des );

   channel Items Add(new RssItem Title = Item Link = Link Description = Des );

  

   var path = Path Combine(AppDomain CurrentDomain BaseDirectory rss xml );

   var template = new XmlTemplate(

        path XmlTemplateScope Compile(path typeof(RssChannel)));

   template Translate(channel) Dump();

  生成XML如下

  view sourceprint?    <channel>

        <title>this is channel title</title>

        <link>;/link>

        <category domain= this > >this is channel category</cate

   gory>

        <noRelacement>不需要替换</noRelacement>

        <skipHours>

          <hour> </hour>

          <hour> </hour>

          <hour> </hour>

        </skipHours>

        <item>

          <title>Item </title>

          <link>Link </link>

          <description>Des </description>

          <channelCategory>this is channel category</channelCategory>

        </item>

        <item>

          <title>Item </title>

          <link>Link </link>

          <description>Des </description>

          <channelCategory>this is channel category</channelCategory>

        </item>

        <item>

          <title>Item </title>

          <link>Link </link>

          <description>Des </description>

          <channelCategory>this is channel category</channelCategory>

        </item>

      </channel>

cha138/Article/program/net/201311/12717

相关参考

知识大全 使用aspx页面作为模板引擎的一种实现

  什么是模板引擎?说白了就是能够自动替换占位符的替换引擎原理上也就是两个步骤找到》替换但是替换不是简单的替换包括  简单变量替换();     &n

知识大全 C# XML序列化实例浅析

C#XML序列化实例浅析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  实现C#XML序列化技术

知识大全 关于java中的对象序列化

  java对象序列化机制一般来讲有两种用途      需要将对象的状态保存到文件中而后能够通过读入对象状态来重新构造对象恢复程序状态      使用套接字在网络上传送对象的程序来说是很有用的    

知识大全 XmlSerializer序列化实体类来操作xml文件

XmlSerializer序列化实体类来操作xml文件  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 JavaIO 6—对象的序列化

JavaIO6—对象的序列化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  对于对象的序列化可能

知识大全 Java中的强大武器--对象的序列化

Java中的强大武器--对象的序列化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  所谓对象序列

知识大全 浅谈Java对象的序列化和反序列化

浅谈Java对象的序列化和反序列化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  当两个进程在进

知识大全 Java对象序列化与RMI

Java深度历险:Java对象序列化与RMI  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  对于

知识大全 ios开发如何进行对象序列化和反序列化

cha138/Article/program/yd/201404/30432

知识大全 使用JID来进行Java对象的高性能序列化

使用JID来进行Java对象的高性能序列化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JID