处理XML文档是我们经常需要进行的一项工作,尤其是在进行网络服务相关编程时,比如更新RSS等。在.NET 3.5中引入了Linq To XML,使得XML文档的读写已经大大简化,而.NET 4.0中最新的dynamic特性,则将简化发挥到了极致。以处理白云黄鹤的“十大”为例,数据源地址为http://www.byhh.net/posttop10.xml,其当前内容为(为使结果显示清晰,去掉了其中的链接地址字段):

<?xml version="1.0" encoding="gb2312" ?><?xml-stylesheet type="text/xsl" href="/style/blue/xsl/posttop.xsl"?><toppost>  <post>    <board>WorldSoccer</board>    <title>大家支持哪队?                                             </title>  </post>  <post>    <board>HUSTStudent</board>    <title>地震了???                                               </title>  </post>  <post>    <board>Picture</board>    <title>想当二奶的有门路了!                                       </title>  </post>  <post>    <board>Picture</board>    <title>轻拍。。。不要太挑剔了                                     </title>  </post>  <post>    <board>Humor</board>    <title>【原创】几个小humor                                        </title>  </post>  <post>    <board>HUSTStudent</board>    <title>院士增选的一个疑问                                         </title>  </post>  <post>    <board>WorldSoccer</board>    <title>卧槽,1:55才开始抽??                                    </title>  </post>  <post>    <board>WorldSoccer</board>    <title>主持MM好靓                                                 </title>  </post>  <post>    <board>TrainFan</board>    <title>1000                                                       </title>  </post>  <post>    <board>Movies</board>    <title>还是推荐熊猫大侠,早上才十块钱.                             </title>  </post></toppost>

好,我们先不管它的链接,仅仅获取其中的版面名(board)和标题(title)。那么使用Linq To XML,处理方法如下:

var doc = XDocument.Load ("http://www.byhh.net/posttop10.xml");foreach (var post in doc.Element ("toppost").Elements ("post")){    Console.WriteLine ("版面:" + post.Element ("board").Value);    Console.WriteLine ("标题:" + post.Element ("title").Value.Trim ());}
输出结果:

版面:HUSTStudent
标题:地震了???
版面:WorldSoccer
标题:大家支持哪队?
版面:Humor
标题:【原创】几个小humor
版面:WorldSoccer
标题:2010年世界杯抽签结果
版面:HUSTStudent
标题:当武大陷入教授门、贪污门时。华中科大又多了两?
版面:Bicycle
标题:雅京行纪录片-1-雅典
版面:Picture
标题:想当二奶的有门路了!
版面:Picture
标题:轻拍。。。不要太挑剔了
版面:Humor
标题:【原创】关于找工作
版面:TrainFan
标题:1000
ress any key to continue . . .

那在.NET 4.0 中,又是怎样的呢,先看我最后的代码:

XDocument doc = XDocument.Load ("http://www.byhh.net/posttop10.xml");dynamic posts = doc.Element ("toppost").AsDynamic ();foreach (var post in posts.post){    Console.WriteLine ("版面:" + post.board);    Console.WriteLine ("标题:" + post.title.Trim ());}

此时,我们已经完全去掉了啰嗦的Element和Elements方法以及Value属性的调用,查询post节点中的board节点、title节点,就只需要post.board和post.title即可,多么方便!而这一切的秘密,就在于dynamic关键字和那个AsDynamic方法。不过,不要以为你新建一个VS2010粘贴以上代码就能运行,“简单是以复杂为支撑的”,之所以能这么写,是因为我实现了两个帮助类XmlNode和XmlNodeList(不是System.Xml命名空间中的那个)来提供dynamic特性的支持,另外还实现了一个静态类来提供XElement上的扩展方法。具体代码如下。

class XmlNode DynamicObjectprivate XElement _element;    public XmlNode (string name)        : this (new XElement (name))    {    }    public XmlNode (XElement element)    {        _element = element;    }    public override bool TryInvokeMember (InvokeMemberBinder binder, object[] args, out object result)    {        string name = binder.Name;        if (String.CompareOrdinal (name, "SelectAll") == 0)        {            IEnumerable<XElement> selectedElements = nullif (args.Length == 0)            {                selectedElements = _element.Descendants ();            }            else            {                selectedElements = _element.Descendants (args[0].ToString ());            }            result = new XmlNodeList (selectedElements);            return true;        }        else if (String.CompareOrdinal (name, "SelectChildren") == 0)        {            IEnumerable<XElement> selectedElements = nullif (args.Length == 0)            {                selectedElements = _element.Elements ();            }            else            {                selectedElements = _element.Elements (args[0].ToString ());            }            result = new XmlNodeList (selectedElements);            return true;        }        return base.TryInvokeMember (binder, args, out result);    }    public override bool TryGetMember (GetMemberBinder binder, out object result)    {        string name = binder.Name;        if (String.CompareOrdinal (name, "Name") == 0)        {            result = _element.Name.LocalName;            return true;        }        else if (String.CompareOrdinal (name, "Parent") == 0)        {            XElement parent = _element.Parent;            if (parent != null)            {                result = new XmlNode (parent);                return true;            }            result = nullreturn true;        }        else if (String.CompareOrdinal (name, "Value") == 0)        {            result = _element.Value;            return true;        }        else if (String.CompareOrdinal (name, "Nodes") == 0)        {            result = new XmlNodeList (_element.Elements ());            return true;        }        else if (String.CompareOrdinal (name, "Xml") == 0)        {            StringWriter sw = new StringWriter ();            _element.Save (sw, SaveOptions.None);            result = sw.ToString ();            return true;        }        else        XAttribute attribute = _element.Attribute (name);            if (attribute != null)            {                result = attribute.Value;                return true;            }            var childNodes = _element.Elements (name).ToArray ();            if (childNodes.Length == 1)            {                if (!childNodes[0].HasElements)                {                    result = childNodes[0].Value;                    return true;                }                result = new XmlNode (childNodes[0]);                return true;            }            else if (childNodes.Length > 1)            {                result = new XmlNodeList (childNodes);                return true;            }        }        return base.TryGetMember (binder, out result);    }    public override bool TrySetMember (SetMemberBinder binder, object value)    {        string name = binder.Name;        if (String.CompareOrdinal (name, "Value") == 0)        {            _element.Value = (value != null) ? value.ToString () : String.Empty;        }        return base.TrySetMember (binder, value);    }}

下面是XmlNodeList,用于处理子节点列:

class XmlNodeList DynamicObjectIEnumerableprivate List<XElement> _elements;    internal XmlNodeList (IEnumerable<XElement> elements)    {        _elements = new List<XElement> (elements);    }    public override bool TryConvert (ConvertBinder binder, out object result)    {        Type targetType = binder.ReturnType;        if (targetType == typeof (IEnumerable))        {            result = thisreturn true;        }        return base.TryConvert (binder, out result);    }    public override bool TryInvokeMember (InvokeMemberBinder binder, object[] args, out object result)    {        if (string.CompareOrdinal (binder.Name, "Item") == 0)        {            if (args.Length == 1)            {                XElement element = _elements[Convert.ToInt32 (args[0])];                result = new XmlNode (element);                return true;            }        }        return base.TryInvokeMember (binder, args, out result);    }    public override bool TryGetMember (GetMemberBinder binder, out object result)    {        if (string.CompareOrdinal (binder.Name, "Length") == 0)        {            result = _elements.Count;            return true;        }        return base.TryGetMember (binder, out result);    }    #region Implementation of IEnumerable    IEnumerator IEnumerable.GetEnumerator ()    {        return new NodeEnumerator (_elements.GetEnumerator ());    }    #endregion    private sealed class NodeEnumerator IEnumerator    private IEnumerator<XElement> _elementEnumerator;        public NodeEnumerator (IEnumerator<XElement> elementEnumerator)        {            _elementEnumerator = elementEnumerator;        }        public object Current        {            get            XElement element = _elementEnumerator.Current;                return new XmlNode (element);            }        }        public bool MoveNext ()        {            return _elementEnumerator.MoveNext ();        }        public void Reset ()        {            _elementEnumerator.Reset ();        }    }}

可以看到,这两个类都继承自DynamicObject,并覆写了基类的一些方法,正因为如此,它们才能对dynamic上的调用做出特殊相应。需要注意的是,虽然我这里是写了两个类,但它们依然是与我的应用无关的,也就是说,我处理任何XML文档,都可以使用上述方法,千万不要以为我为了处理白云黄鹤的十大而特别写了这两个类。这两个类的代码参考了nikhilk的博客(http://www.nikhilk.net/CSharp-Dynamic-Programming-REST-Services.aspx)的内容,不过他的实现是基于.NET 4.0 CTP的,在beta2上已经无法使用。

最后贴上那个扩展方法AsDynamic()的实现:

static class XmlExtensionpublic static XmlNode AsDynamic (this XElement source)    {        return new XmlNode (source);    }    public static XmlNodeList AsDynamic (this IEnumerable<XElement> source)    {        return new XmlNodeList (source);    }}

转载于:https://www.cnblogs.com/wwwzzg168/p/3568977.html

使用dynamic特性处理XML文档相关推荐

  1. C# 生成 XML 文档时出错。使用 XmlInclude 或 SoapInclude 特性静态指定非已知的类型

    报错: 生成 XML 文档时出错.使用 XmlInclude 或 SoapInclude 特性静态指定非已知的类型 原因: c# xml object类型序列化失败 解决: 对于obejct属性.字段 ...

  2. 《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一3.7.5 使用StAX写出XML文档

    3.7.5 使用StAX写出XML文档 在前一节中,你看到了如何通过写出DOM树的方法来产生XML文件.如果这个DOM树没有其他任何用途,那么这种方式就不是很高效. StAX API使我们可以直接将X ...

  3. 使用JAXP对xml文档进行DOM解析基础

    XML解析方式分为两种:dom和sax         dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式.        sax ...

  4. xml教程之java解析xml文档

    1.java解析xml文件介绍 XML解析方式分为两种:DOM方式和SAX方式 DOM:Document Object Model,文档对象模型.这种方式是W3C推荐的处理XML的一种方式. SAX: ...

  5. 【Qt】DOM读取XML文档

    00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. XML文档示例 04. DOM读取XML文档内容 05. 预留 06. 附录 01. 概述 DOM(Document Ob ...

  6. [Qt教程] 第27篇 XML(一)使用DOM读取XML文档

    [Qt教程] 第27篇 XML(一)使用DOM读取XML文档 楼主  发表于 2013-5-21 21:14:28 | 查看: 1001| 回复: 14 使用DOM读取XML文档 版权声明 该文章原创 ...

  7. XML——文档类型定义(DTD-Document Type Definition)

    [0]README 0.1)本文文字描述转自 core java volume 2 , 旨在理解 XML--文档类型定义(DTD-Document Type Definition) 的基础知识: 0. ...

  8. ssis导入xml_使用SSIS包将XML文档导入SQL Server表

    ssis导入xml This article guides you through importing XML documents into SQL tables using SSIS package ...

  9. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    原文:[Win 10应用开发]Adaptive磁贴模板的XML文档结构 在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴 ...

最新文章

  1. 比尔盖茨护犊子 称iPad让大批用户沮丧
  2. 程序员,应该掌握的英语词汇
  3. ASP.NET中文件上传下载方法集合
  4. JTS基本概念和使用
  5. ORACLE 进入sqlplus的协议适配器错误
  6. Ubuntu 10.04屏幕录像软件Xvidcap安装及详细配置
  7. Python datetime time
  8. 解决许可证兼容性问题,Ubuntu 内核将内置 ZFS
  9. SQL Server 2008的安装
  10. .Net 程序员应该知道的工具和网站
  11. Http协议详解(深入理解)
  12. javascript 设为首页 | 加入收藏夹 JS代码
  13. 工作流软件哪个好?介绍几款知名的工作流软件
  14. 计量广义差分操作过程_计量学堂 | 计量经济学最基本的31个问题
  15. 网络拥塞控制,对越远的流量越宽容
  16. [AHOI2014/JSOI2014]骑士游戏
  17. 人工智能在制造业的工程化应用实践----工业软件讲坛第九次讲座
  18. 成人教育:毕业信息自我鉴定
  19. houdini-houdini记录
  20. yaskawa 机器人控制

热门文章

  1. 站长们 技术不是你生存的全部
  2. hdu2604 矩阵快速幂
  3. POJ 1386 欧拉路的判定
  4. 【数字信号处理】周期序列 ( 周期序列示例 3 | 判断序列是否是周期序列 )
  5. 【Groovy】闭包 Closure ( 闭包定义 | 闭包类型 | 查看编译后的字节码文件中的闭包类型变量 )
  6. 【计算理论】计算复杂性 ( 多项式等价引入 | 多项式时间规约 )
  7. 【Android 内存优化】Bitmap 长图加载 ( BitmapRegionDecoder 简介 | BitmapRegionDecoder 使用流程 | 区域解码加载示例 )
  8. 01.Python基础-3.集合容器
  9. Beta阶段——第4篇 Scrum 冲刺博客
  10. Xilinx ISE 14.7 安装教程