简化 XML 读写

来源:互联网 发布:acm网络赛在线报名 编辑:程序博客网 时间:2024/05/05 02:39

简化 XML 读写

使用 XPath 等查询定义显著简化 DOM 编码

developerWorks 文档选项 将此页作为电子邮件发送

将此页作为电子邮件发送



级别: 初级

Cameron Laird (claird@phaseit.net), 副总裁, Phaseit, Inc.

2007 年 7 月 02 日

合理使用 XML,XPath 就能够显著地简化和加速应用程序。如果您的工具包中还没有 XPath,那么现在就把它添加进来吧。使用 Python 简要编写的具体示例使查询习语的出现更为自然。

XPath 理应成为您的朋友。

如果您很少使用 XML 进行开发,并且从未使用过 XPath,那么您将有机会开发性能更强、可维护性更佳的应用程序。这篇文章详细介绍了一些特定的示例,用来演示在简单的 XML 处理中,查询方法能够造成多大的影响。

基础知识

要确保 XPath 进展顺利,需考虑一些基础原理:

  • 下列示例使用 Python 编写
  • 以前您可能多次听说 Xsomething 很有用 —— 它设计用于解决特定的和实际的问题,它经过委员会的一致通过,等等。我承认我就听说过。虽然 XPath 与 XML 中所有其他的 Alphabet Soup 不同;但是它确实 非常有用的工具。对于实际投身编程工作的程序员来说,XPath 是最具学习价值的 XML 定义之一,其重要性仅次于 XML 本身和 XHTML。
  • 您不需要 XPath。您是一名实际动手编程的 XML 程序员,您的应用程序已经具备了所需的功能。可是关键在于,传统的过程编程不能很好地解决常见的 XML 问题。虽然程序能正确地运行,但是只需少量的查询代码就能使您的程序具有更好的可读性、更易于维护,并且在很多情况下,运行得更快,有时这种效果非常明显。使用这些代码的目的不是要抛弃现有的正常运作的编程方法,而是要学习一些辅助技巧,使用这些技巧可取得立杆见影的效果。

 

developerWork 上 XML 专区的读者大多致力于 C、C++、或 Java 开发。但 Python Python 是一种很值得展示的工具,因为它读起来像流线型的伪代码,并且广泛可用。即便是 Python 的初学者也能理解后继的用法。

类似于许多其他语言,Python 支持大量的 XML 库。过去常常会不知道从何处开始。然而,随着 Python 2.5 版本的推出,Fredrik Lundh 的非凡的 ElementTree 模块成为了标准;本文的示例将使用这个库。库本身很小,并能附加到任何 1.5.2 以上的 Python 版本中,参考资料 中对此作出了解释。正确安置好 ElementTree 后,执行示例程序所需的一切条件都已就绪。

XML 编程模型

目前大多数 XML 编程都是基于文档对象模型(Document Object Model,DOM )。这一模型将 XML 实例视为一个元素树,使用标记对元素进行标识,很多元素都有属性和/或子元素。XML 编程是一项繁重的工作,因为处理必须通过树导航到各个元素。例如,考虑 developerWorks 在开发 developerWorks 文章的内容的过程中所使用的模板 XML 。这看上去与 XHTML 极为相似。它的模式简单易懂,这当然是与工业应用程序(可能是用于采集机器或财务事项的众多细节)中常见的 XML 实例相比而言。即便是使用这个简单的模型,如果您想要报告文本中的所有锚点标记 —— 所有标记为 <a> 的元素 —— 那么您需要导航整个文档,到一个任意的嵌套深度。简单的非递归过程表达式并不能访问所有的元素,尽管许多库都包含有帮助功能,可以用于遍历树。

结果:用于报告所有锚点的一个简单的程序将类似于:
清单 1. 基于 DOM 的代码,用于报告所有的锚点

                        import elementtree.ElementTree        def detail_anchor(element):        if element.tag == "a":            attributes = element.attrib            if "href" in attributes.keys():                print "'%s' is at URL '%s'." % (element.text,                                                attributes['href'])            if "name" in attributes.keys():                print "'%s' anchors '%s'." % (element.text,                                                attributes['name'])        def report(element):        detail_anchor(element)        for x in element.getchildren():            report(x)        report(elementtree.ElementTree.parse("draft2.xml").getroot())  

使用下面描述的 5.5.1 引用模板,将产生类似如下的输出:
清单 2. 清单 1 中的程序产生的报告

                        'related developerWorks content' is at 'http://www.ibm.com/developerworks'.    'entire series' is at 'http://www.ibm.com/...'       ...    'IBM product evaluation versions' is at 'http://www.ibm.com/...'   

如果有一种标准的方法可用来查询 DOM 实例、解压指定元素、属性和标记的信息,那么可带来多大的简化?您自己看吧:


清单 3. 基于 XPath 的与清单 1 等价的代码。
                    import elementtree.ElementTree        def detail_anchor(element):        if element.tag == "a":            attributes = element.attrib            if "href" in attributes.keys():                print "'%s' is at URL '%s'." % (element.text,                                                attributes['href'])            if "name" in attributes.keys():                print "'%s' anchors '%s'." % (element.text,                                                attributes['name'])        for element in /           elementtree.ElementTree.parse("draft2.xml").findall("//a"):        detail_anchor(element)    

清注意,“//a” 在英语中的意思是 “在整个文档中搜索标记为 ‘a’ 的元素”。从本质上说,清单 3 产生的输出与 清单 2 的输出是相同的。

ElementTree 安装

我们希望 Python 的安装附有ElementTree。虽然大家会乐意阅读代码清单,但如果能亲自执行代码则更好,而根据自己的想法对代码进行更改并实验,这样将会甚至更佳。

这非常容易完成。与我使用过的许多笨拙的 XML 工具包相比,ElementTree 只需几分钟即可安装好并开始使用。

首先,您需要 Python。大多数当前的 UNIX 版本(包括 MacOS 和几乎所有的 Linux 变种)都内置了 Python。对于 Windows,请参阅 参考资料 中的 ActivePython。

正确安置 Python:

  1. 检索elementtree 源文件包(在 ElementTree 主页中按 参考资料 中的描述操作)。
  2. 解压该包。
  3. 导航到正确的目录(大概类似于 elementtree-1.2.6-20050316/ —— 关键是 setup.py 所在的目录)。
  4. 在命令行调用 python setup.py install

 

全部完成。所需操作就是这些。要检验安装,运行交互式 Python shell 并请求 import elementtree.ElementTree

比较 清单 1清单 3。前者已经够简单了 —— 可是后者更加简单。它消除了明确地指定递归的需求。更重要的是,XPath 代码根据 XML(逻辑)标记,而不是结构。标记更接近于人的思维,并且持续时间长,从这个角度来看,结构是相对短暂的实现细节。通过使用更复杂的查询,XPath 的声明性样式与传统的面向结构的过程搜索实现相比,其优势更加明显。

本文的意义在于,能够把 XPath 融入到现有的 XML 程序开发中,并能立即获得性能和可维护性上的提高。对于我来说,这更像是在使用汇编程序、编译器、和更高阶的语言:我可以完全使用机器语言编写整个程序,但是学习高生产率的方法会简单划算。此外,XPath 通常能提高 手工编码的搜索的性能。

可是,这样却产生了一个问题:有方法改进 XPath 吗?是的,当然有 —— 但是有一些限定。XQuery 和 XSLT 是另外两种接受程度与 XPath 相当的 XML 定义(XSLT 可能是它们三者中使用最为广泛的,而 Xquery 的有用实现则最少)。在声明重点上 XSLT 与 XPath 类似,而 Xquery 在 XPath 的查询中加入了过程的功能。两者都能生成模板 —— 简要地说,嵌入可识别的 XML 代码段的查询 —— 或多或少符合语言习惯。这一点值得注意,因为一些 XML 理论家建议把模板作为理想的表示形式。

但是整体来说,相对于 XPath 产生的巨大效益而言,XQuery、XSLT 或此类特定于语言的查询包(如 Amara、XQJ、或JAXP)所带来的好处都是递增的。参考资料 中提供的 Uche Ogbuji 撰写的论文清晰地比较了采用各种不同方式解决的示例问题。只有在感觉 XML 处理相当复杂的时候,才使用这些更专业的接口。但是现在就开始使用 XPath!

其它示例

这篇文章的目的是激发您使用 XPath,而不是教您使用它。我希望您可以清楚地认识到学习 XPath 并不会花费太多精力。

同时,我们希望知道使用 XPath 可实现哪些功能。清单 3 中的查询使用 //a 作为一个简单的例子。最后,您将学习更复杂的查询功能,例如 /parent/child[@attr='value'],它指定所有 “parent” 的子节点 “child” 并指定属性 “attr” 的值为 “value”。另外两个例子://@*,它检查所有标记的所有属性;//tr/td|th 检索 tr 里面的所有 tdth 元素。

性能

虽然性能测量总是需要缩小至一种特定的测量方法,但是对 XPath 性能的思考需要一些上下文。通俗地讲,XPath 比您所能达到的速度更快。在大型的、复杂的程序中,性能至关重要,XPath 查询比同等的手工编写的过程代码运行得更快(有时要快很多)。从原则上说,您可使用已有的关于数据内容或布局的知识来编写一个可快速运行的巧妙的查询。但在实践中,使用 XPath 产生的效果类似于使用高级语言(HLL)(而不是汇编程序或 C 语言)所产生的效果:只需少许的工作,开发人员就能够完成一个正确运行的程序,而 HLL 的所有表面上固有的速度缺点都可通过较高级的特定于应用程序的算法来弥补。

使用完全相同的方式,XPath 对一些不可忽视问题简化了编码。在这些问题中,速度造成的影响足以使程序员利用空闲时间小心地开发自己的解决方案。基于 XPath 的解决方案不仅更易于纠错和维护,而且至少是速度快。

此外,一些 XPath 实现是非常细致地编写的,其内存使用率比普通的过程搜索更高。在这些例子中,基于 XPath 的编码能极大地提高搜索速度 —— 十倍或更高。

没有展示特定的测量方法来说明这些问题确实令人沮丧。虽然,任何特定的对比都会产生误导;但是 XPath 的相对性能取决于开发语言、特定的 XPath 实现、XML 查询图像、搜索、和运行时可用内存(大多数情况)的布局。学习如何进行简单的计时,并学习在您的 应用程序的数据集上测试 XPath。如果您的经验和我差不多,那么您时常会发现 XPath 只有原生编码一半的速度,对于一些小问题尤为显著,但是与其它语言相比速度还是要快一个级别。

结束语

分享这篇文章……

digg 将本文提交到 Digg del.icio.us 发布到 del.icio.us Slashdot 提交到 Slashdot!

XPath 是一种 XML 工具,使用成本极低:您可能已通过使用的开发语言将其构建到 XML 库中。同时,XPath 具有显著提高性能的潜力,并且其简单的表示实实在在地简化了编程和维护。此外,还有大量的 XPath 教程能帮助您学习所需知识。最终,您将发现在 XPath 上的投入能很快带来收益。

一旦了解了 XPath,您也将能更好地判断是否使用 XML 时太费劲,需要利用一些高级工具(如XQuery 和 XSLT)来使您受益。

务必阅读参考资料中列出的资料,它们能帮助您立即开始使用 XPath 编程。



参考资料

学习
  • 您可以参阅本文在 developerWorks 全球网站上的 英文原文

  • developerWork 的 “可爱的 Python” 专栏:为什么要使用 Python 来解释 XPath?有关这一语言优点的细节,请参见 David Mertz 的专栏。近来,它得到了广泛的应用,而且就算是完全不了解它的程序员往往也会发现它易于阅读。

  • ActivePython:探索 ActivePython,依据 ActivePython 的主页,ActivePython 是 Python 的一种有质量保证的可安装的发行版。因为其安装的可靠性,作者特别建议对 Python 感兴趣的 Windows 用户使用 ActivePython。

  • ElementTree 主页:查看由 Fredrik Lundh 编写和维护的 ElementTree 包装器如何添加代码,以便将 XML 文件作为 Element 对象的树进行加载,并将它们保存回来。除了 上面侧栏 中讨论的安装简单之外,ElementTree 还附带了各种实现以利用其它的库和提高性能。

  • 大量 关于 XPath 的教程中,可以从这里开始学习:
    • XPath 入门(Bertrand Portier,developerWorks,2004 年 5 月):学习什么是 XPath,XPath 语言的语法和语义,如何使用 XPath 位置路径,如何使用 XPath 表达式,如何使用 XPath 函数,以及 XPath 如何与 XSLT 关联。本教程介绍的是 XPath 1.0 版。
    • XPath tutorial(Miloslav Nic 和 Jiri Jirat,zvon):通过大量的例子学习所选的 XPath 特性。

  • XML Path Language (XPath) 规范:有关 XSL Transformations [XSLT] 和 Xpointer 共享功能的常用语法和语义,请阅读 W3C 维护规范。

  • 实用数据绑定: 使用 XPath 作为数据绑定工具,第 2 部分(Brett McLaughlin,developerWorks,2006 年 1 月):使用 JAXP API 执行 XPath 查询并在 Java 中使用 XPath 进行编码。

  • XGrep 是一种类似于 grep 的 XML 文档工具。” Xgrep 是一款非常出色的工具,开发人员应该时刻把它放在身边。这篇文章使用 Python 作为示例演示了 XML 编程。但是,如果 Cameron 的介绍重点是 XPath 本身,而不是如何使用它编程,则他就会根据 XGrep 进行讲授。

  • 阅读下列两篇 developerWork 的介绍性文章:
    • XQuery 简介(Howard Katz,2006 年 2 月更新):阅读 W3C 提议的 XML 查询语言标准。
    • XSLT 是什么类型的语言?(Michael Kay,2001 年 2 月):把 XSLT 放置在上下文中 —— 它的起源、擅长方面以及为什么要使用它。

  • 看看两位作者的不同见解,但是两篇文章都是经过仔细的斟酌而写成的;它们可很好地相互补充。
    • A conversation with Jonathan Robie about XQuery:在这个有趣的访问中,Jonathan Robie 说明了 XML 查询语言的意义所在。
    • Is XQuery an omni-tool?:Ogbuji 特别关注 Xquery。Ogbuji 在这些 会议记录 中详细说明了XPath、XSLT、和 XQuery 之间的关系。

  • developerWork 中国网站 XML 专区:了解 XML 的所有信息。

  • IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。

  • XML 技术文档库: developerWorks XML 专区提供了大量技术文章和提示、教程、标准以及 IBM 红皮书。

  • developerWorks 技术活动和网络广播:随时关注技术的最新进展。


获得产品和技术
  • IBM 试用版软件:使用 IBM 试用软件构建您的下一个开发项目,可从 developerWorks 直接下载获得。


讨论
  • XML 专区讨论论坛:参与任何以 XML 为中心的论坛。


关于作者

Photo of Cameron Laird

Cameron Laird 是 developerWorks 长期投稿者和前专栏作家。他经常编写关于促进其公司应用程序开发的项目的文章,主要关注可靠性、安全性和最初不是为协作而设计的系统集成。


 
原创粉丝点击