Fredrik Lundh
![](/icons/45380de.gif)
ElementTree 模块是
![](/icons/45380yi.gif)
种日益受欢迎
![](/icons/45380de.gif)
API
![](/icons/45380dou.gif)
用于以 Python 语言进行轻量级且高速
![](/icons/45380de.gif)
XML 文档操作
![](/icons/45380dou2.gif)
在这篇专栏文章中
![](/icons/45380dou.gif)
David 将 ElementTree 和其它几种致力于以对象树方式处理 XML 例子
![](/icons/45380de.gif)
库
![](/icons/45380dou.gif)
尤其是他自己
![](/icons/45380de.gif)
gnosis.xml.object
![](/icons/45380if.gif)
y 模块
![](/icons/45380dou.gif)
作了个比照
![](/icons/45380dou2.gif)
在本专栏以前
![](/icons/45380de.gif)
文章中
![](/icons/45380dou.gif)
我已讨论了
![](/icons/45380yi.gif)
些 XML 库
![](/icons/45380dou.gif)
它们旨在以给定编程语言仿真最常见
![](/icons/45380de.gif)
本机操作
![](/icons/45380dou2.gif)
其中
![](/icons/45380dou.gif)
我首先介绍了我自己
![](/icons/45380de.gif)
、用于 Python
![](/icons/45380de.gif)
gnosis.xml.object
![](/icons/45380if.gif)
y
![](/icons/45380dou2.gif)
另外我也专门用了几篇文章介绍 Haskell
![](/icons/45380de.gif)
HaXml 和 Ruby
![](/icons/45380de.gif)
REXML
![](/icons/45380dou2.gif)
虽然我还未在这里讨论过
![](/icons/45380dou.gif)
但 Java
![](/icons/45380de.gif)
JDOM和 Perl
![](/icons/45380de.gif)
XML::Grove也有着类似
![](/icons/45380de.gif)
目标
![](/icons/45380dou2.gif)
最近
![](/icons/45380dou.gif)
我在 comp.lang.python 新闻组上注意到
![](/icons/45380yi.gif)
些帖子
![](/icons/45380dou.gif)
提到了 Fredrik Lundh
![](/icons/45380de.gif)
ElementTree
![](/icons/45380dou.gif)
![](/icons/45380yi.gif)
个用于 Python
![](/icons/45380de.gif)
本机 XML 库
![](/icons/45380dou2.gif)
当然
![](/icons/45380dou.gif)
在 Python
![](/icons/45380de.gif)
标准分发版中早已包括了几个 XML API
![](/icons/45380dou.gif)
包括:DOM 模块、SAX 模块、 expat包装器和不赞成使用
![](/icons/45380de.gif)
xmllib
![](/icons/45380dou2.gif)
其中
![](/icons/45380dou.gif)
只有 xml.dom将 XML 文档转换为内存中
![](/icons/45380de.gif)
对象
![](/icons/45380dou.gif)
您可以通过节点上
![](/icons/45380de.gif)
思路方法
![](/icons/45380diaoyong.gif)
来操作这些对象
![](/icons/45380dou2.gif)
实际上
![](/icons/45380dou.gif)
您将发现存在几种区别
![](/icons/45380de.gif)
Python DOM 实现
![](/icons/45380dou.gif)
其特性各有区别:
xml.minidom是
![](/icons/45380yi.gif)
个基本
![](/icons/45380de.gif)
实现
![](/icons/45380dou2.gif)
xml.pulldom只在需要时构建被访问
![](/icons/45380de.gif)
子树
![](/icons/45380dou2.gif)
考虑到速度问题
![](/icons/45380dou.gif)
4Suite
![](/icons/45380de.gif)
cDomlette( Ft.Xml.Domlette)用 C 语言构建 DOM 树
![](/icons/45380dou.gif)
避免了使用 Python 回调
![](/icons/45380dou2.gif)
当然
![](/icons/45380dou.gif)
出于我身为作者
![](/icons/45380de.gif)
自负
![](/icons/45380dou.gif)
我最想做
![](/icons/45380de.gif)
是将 ElementTree和我自己
![](/icons/45380de.gif)
gnosis.xml.object
![](/icons/45380if.gif)
y及其它几种目
![](/icons/45380de.gif)
和行为都极其接近
![](/icons/45380de.gif)
库进行比较
![](/icons/45380dou2.gif)
ElementTree
![](/icons/45380de.gif)
目标是以数据结构
![](/icons/45380de.gif)
形式存储 XML 文档
![](/icons/45380de.gif)
表示
![](/icons/45380dou.gif)
这些数据结构
![](/icons/45380de.gif)
行为方式同您在 Python 中考虑数据
![](/icons/45380de.gif)
方式非常相似
![](/icons/45380dou2.gif)
这里
![](/icons/45380de.gif)
关注焦点在于以 Python 进行编程
![](/icons/45380dou.gif)
而不是使您
![](/icons/45380de.gif)
编程风格顺应 XML
![](/icons/45380yi.gif)
些基准测试
我
![](/icons/45380de.gif)
同事 Uche Ogbuji 曾为另
![](/icons/45380yi.gif)
个出版物写过
![](/icons/45380yi.gif)
篇有关 ElementTree
![](/icons/45380de.gif)
短文
![](/icons/45380dou2.gif)
(请参阅 参考资料
![](/icons/45380dou2.gif)
)他对 ElementTree和 DOM 做了几个测试
![](/icons/45380dou.gif)
其中的
![](/icons/45380yi.gif)
比较了它们
![](/icons/45380de.gif)
相对速度和内存消耗
![](/icons/45380dou2.gif)
Uche 选用了他自己
![](/icons/45380de.gif)
cDomlette 作为比较对象
![](/icons/45380dou2.gif)
很遗憾
![](/icons/45380dou.gif)
我不能在我使用
![](/icons/45380de.gif)
Mac OSX 机器上安装 4Suite 1.0a1(我正在研究
![](/icons/45380yi.gif)
种变通思路方法)
![](/icons/45380dou2.gif)
然而
![](/icons/45380dou.gif)
我可以根据 Uche
![](/icons/45380de.gif)
评估来估计大致性能 - 他指出 ElementTree同 cDomlette相比
![](/icons/45380dou.gif)
速度慢 30%
![](/icons/45380dou.gif)
但消耗
![](/icons/45380de.gif)
内存也要少 30%
![](/icons/45380dou2.gif)
我极为好奇
![](/icons/45380de.gif)
是
![](/icons/45380dou.gif)
ElementTree和 gnosis.xml.object
![](/icons/45380if.gif)
y在速度和内存上比较
![](/icons/45380dou.gif)
结果会如何
![](/icons/45380dou2.gif)
实际上
![](/icons/45380dou.gif)
的前我从未对我
![](/icons/45380de.gif)
模块进行过非常精确
![](/icons/45380de.gif)
基准测试
![](/icons/45380dou.gif)
![](/icons/45380yinwei.gif)
我始终没有
![](/icons/45380yi.gif)
个具体
![](/icons/45380de.gif)
可比对象
![](/icons/45380dou2.gif)
我选择了两个过去我曾用于基准测试
![](/icons/45380de.gif)
文档:莎士比亚
![](/icons/45380de.gif)
哈姆雷特289 KB XML 版本
![](/icons/45380dou.gif)
及 3 MB XML Web 日志
![](/icons/45380dou2.gif)
我创建了几个脚本
![](/icons/45380dou.gif)
仅用于将 XML 文档解析为几种工具
![](/icons/45380de.gif)
对象模型
![](/icons/45380dou.gif)
但此外不作任何其它操作:
清单 1. 对用于 Python
![](/icons/45380de.gif)
XML 对象模型计时
![](/icons/45380de.gif)
脚本
% cat time_xo.py
import sys
from gnosis.xml.object
y
import XML_Object
y,EXPAT
doc = XML_Object
y(sys.stdin,EXPAT).make_instance![](/icons/45380kh.gif)
---
% cat time_et.py
import sys
from elementtree
import ElementTree
doc = ElementTree.parse(sys.stdin).getroot![](/icons/45380kh.gif)
---
% cat time_minidom.py
import sys
from xml.dom
import minidom
doc = minidom.parse(sys.stdin)
在所有 3个案例中
![](/icons/45380dou.gif)
![](/icons/45380chengxu.gif)
对象
![](/icons/45380de.gif)
创建非常类似
![](/icons/45380dou.gif)
对于 cDomlette 也
![](/icons/45380yi.gif)
样
![](/icons/45380dou2.gif)
我在另
![](/icons/45380yi.gif)
个窗口观察 top
![](/icons/45380de.gif)
输出
![](/icons/45380dou.gif)
以评估内存使用情况;每种测试进行 3遍以确保其
![](/icons/45380yi.gif)
致性
![](/icons/45380dou.gif)
并取其结果
![](/icons/45380de.gif)
平均值(每次运行使用
![](/icons/45380de.gif)
内存是相同
![](/icons/45380de.gif)
)
![](/icons/45380dou2.gif)
图 1. 以 Python 编写
![](/icons/45380de.gif)
XML 对象模型
![](/icons/45380de.gif)
基准测试结果
![](http://www.crazycoder.cn/WebFiles/20091/25e83ff0-a800-4b73-8a0b-bf8e62321981.g<img src='/icons/45380if.gif' />)
>>> doc.text, doc.tail
('begin', None)
>>> doc.find('b').text, doc.find('b').tail
('inside', 'middle')
>>> doc.find('c').text, doc.find('c').tail
('inside', 'end')
结束语
ElementTree是
![](/icons/45380yi.gif)
个非常不错
![](/icons/45380de.gif)
模块
![](/icons/45380dou.gif)
和 DOM 相比
![](/icons/45380dou.gif)
它提供了
![](/icons/45380yi.gif)
个更轻量级
![](/icons/45380de.gif)
对象模型
![](/icons/45380dou.gif)
用于以 Python 处理 XML
![](/icons/45380dou2.gif)
虽然我没有在本文中提及
![](/icons/45380dou.gif)
ElementTree在从头生成 XML 文档方面和它在操作现有
![](/icons/45380de.gif)
XML 数据方面
![](/icons/45380yi.gif)
样出色
![](/icons/45380dou2.gif)
作为和的类似
![](/icons/45380de.gif)
库 gnosis.xml.object
![](/icons/45380if.gif)
y
![](/icons/45380de.gif)
作者
![](/icons/45380dou.gif)
我无法完全客观地评价 ElementTree;尽管如此
![](/icons/45380dou.gif)
和那些 ElementTree所提供
![](/icons/45380de.gif)
思路方法相比
![](/icons/45380dou.gif)
我始终尝试在 Python
![](/icons/45380chengxu.gif)
中用我自己
![](/icons/45380de.gif)
思路方法更简单自然地予以实现
![](/icons/45380dou2.gif)
ElementTree 通常仍利用节点
![](/icons/45380de.gif)
思路方法来操作数据结构
![](/icons/45380dou.gif)
而不是像人们通常处理应用
![](/icons/45380chengxu.gif)
中构建
![](/icons/45380de.gif)
数据结构那样直接访问节点属性
![](/icons/45380dou2.gif)
然而
![](/icons/45380dou.gif)
在有些方面
![](/icons/45380dou.gif)
ElementTree很出色
![](/icons/45380dou2.gif)
使用 XPath 访问深层嵌套元素要比手工递归搜索容易得多
![](/icons/45380dou2.gif)
显然
![](/icons/45380dou.gif)
在 DOM 中也可使用 XPath
![](/icons/45380dou.gif)
但代价是形成
![](/icons/45380yi.gif)
个过于庞大且不够统
![](/icons/45380yi.gif)
![](/icons/45380de.gif)
API
![](/icons/45380dou2.gif)
ElementTree 所有
![](/icons/45380de.gif)
Element 节点
![](/icons/45380de.gif)
工作方式是
![](/icons/45380yi.gif)
致
![](/icons/45380de.gif)
![](/icons/45380dou.gif)
不像 DOM
![](/icons/45380de.gif)
节点类型那样“装饰华丽”