进一步了解Python中的XML 工具


Posted in Python onApril 13, 2015

模块:xmllib

xmllib 是一个非验证的低级语法分析器。应用程序员使用的 xmllib 可以覆盖 XMLParser 类,并提供处理文档元素(如特定或类属标记,或字符实体)的方法。从 Python 1.5x 到 Python 2.0+ 以来, xmllib 的使用方法并没变化;在绝大多数情况下更好的选择是使用 SAX 技术,它也是种面向流的技术,对语言和开发者来说更为标准。

本文中的示例与原来专栏中的相同:包括一个叫做 quotations.dtd 的 DTD 以及这个 DTD 的文档 sample.xml (请参阅 参考资料,以获取本文中提到的文件的档案)。以下的代码显示了 sample.xml 中每段引言的前几行,并生成了非常简单的未知标记和实体的 ASCII 指示符。经过分析的文本作为连续流来处理,所使用的任何累加器都由程序员负责(如标记中的字符串 (#PCDATA),或所遇到的标记的列表或词典)。
清单 1: try_xmllib.py

import
         xmllib, string
    
    classQuotationParser

        (xmllib.XMLParser):
  """Crude xmllib extractor for quotations.dtd document"""
  
    
    def__init__

        (self):
    xmllib.XMLParser.__init__(self)
    self.thisquote = ''       
    
    # quotation accumulator
     
     
     defhandle_data

        (self, data):
    self.thisquote = self.thisquote + data
  
    
    defsyntax_error
        (self, message):
    
    
    pass
  defstart_quotations
        (self, attrs): 
    
    # top level tag
         
     
     print

         '--- Begin Document ---'
  
    
    defstart_quotation
        (self, attrs):
    
    
    print
         'QUOTATION:'
  
    
    defend_quotation
        (self):
    
    
    print

         string.join(string.split(self.thisquote[:230]))+'...',
    
    
    print

         '('+str(len(self.thisquote))+' bytes)\n'
    self.thisquote = ''
  
    
    defunknown_starttag

        (self, tag, attrs):
    self.thisquote = self.thisquote + '{'
  
    
    defunknown_endtag

        (self, tag):
    self.thisquote = self.thisquote + '}'
  
    
    defunknown_charref

        (self, ref):
    self.thisquote = self.thisquote + '?'
  
    
    defunknown_entityref

        (self, ref):
    self.thisquote = self.thisquote + '#'
    
    if

         __name__ == '__main__':
  parser = QuotationParser()
  
    
    for
         c 
    
    in
         open("sample.xml").read():
    parser.feed(c)
  parser.close()

验证

您可能需要展望标准 XML 支持的未来的原因是,在进行语法分析的同时需要进行验证。不幸的是,标准 Python 2.0 XML 包并不包括验证型语法分析器。

xmlproc 是 python 原有的语法分析器,它执行几乎完整的验证。如果需要验证型语法分析器, xmlproc 是 Python 当前唯一的选择。而且, xmlproc 提供其它语法分析器所不具备的各种高级和测试接口。

选择一种语法分析器

如果决定使用 XML 的简单 API (SAX) -- 它应该用于复杂的事物,因为其它大部分工具都是在它的基础上建立的 -- 将为您完成许多语法分析器的分类工作。 xml.sax 模块包含一个自动选择“最佳”语法分析器的设施。在标准 Python 2.0 安装中,唯一能选择的语法分析器是 expat ,它是种 C 语言编写的快速扩展。然而,也可以在 $PYTHONLIB/xml/parsers 下安装另一个语法分析器,以备选择。设置语法分析器很简单:
清单 2: Python 选择最佳语法分析器的语句

import
         xml.sax
parser = xml.sax.make_parser()

您还可以通过传递参数来选择特定的语法分析器;但考虑到可移植性 -- 也为了对今后更好的语法分析器的向上兼容性 -- 最佳方法是使用 make_parser() 来完成工作。

您可以直接导入 xml.parsers.expat 。如果这样做,您就能获得 SAX 界面并不提供的一些特殊技巧。这样, xml.parsers.expat 与 SAX 相比有些“低级”。但 SAX 技术非常标准,对面向流的处理也非常好;大多数情况下 SAX 的级别正合适。通常情况下,由于 make_parser() 函数已经能获得 expat 提供的性能,因此纯速度的差异很小。

什么是 SAX

考虑到背景因素,回答什么是 SAX 的较好答案是:

    SAX (XML 的简单 API)是 XML 语法分析器的公用语法分析器接口。它允许应用程序作者编写使用 XML 语法分析器的应用程序,但是它却独立于所使用的语法分析器。(将它看作 XML 的 JDBC。)(Lars Marius Garshol,SAX for Python)

SAX -- 如同它提供的语法分析器模块的 API -- 基本上是一个 XML 文档的顺序处理器。使用它的方法与 xmllib 示例极其相似,但更加抽象。应用程序员将定义一个 handler 类,而不是语法分析器类,该 handler 类能注册到任何所使用的语法分析器中。必须定义 4 个 SAX 接口(每个接口都有几个方法):DocumentHandler、DTDHandler、EntityResolver 和 ErrorHandler。创建语法分析器除非被覆盖,否则它还连接默认接口。这些代码执行与 xmllib 示例相同的任务:
清单 3: try_sax.py

"Simple SAX example, updated for Python 2.0+"
    
    import
         string
    
    import
         xml.sax
    
    from
         xml.sax.handler 
    
    import
         *
    
    classQuotationHandler

        
  (ContentHandler):
  """Crude extractor for quotations.dtd compliant XML document"""
  
    
    def__init__

        
  (self):
    self.in_quote = 0
    self.thisquote = ''
  
    
    defstartDocument
        
  (self):
    
    
    print

         '--- Begin Document ---'
  
    
    defstartElement

        
  (self, name, attrs):
    
    
    if

         name == 'quotation':
      
    
    print

         'QUOTATION:'
      self.in_quote = 1
    
    
    else:
    
    
      self.thisquote = self.thisquote + '{'
  
    
    defendElement

        
  (self, name):
    
    
    if

         name == 'quotation':
      
    
    print

         string.join(string.split(self.thisquote[:230]))+'...',
      
    
    print

         '('+str(len(self.thisquote))+' bytes)\n'
      self.thisquote = ''
      self.in_quote = 0
    
    
    else:
    
    
      self.thisquote = self.thisquote + '}'
  
    
    defcharacters
        
  (self, ch):
    
    
    if

         self.in_quote:
      self.thisquote = self.thisquote + ch
    
    if
         __name__ == '__main__':
  parser = xml.sax.make_parser()
  handler = QuotationHandler()
  parser.setContentHandler(handler)
  parser.parse("sample.xml")

与 xmllib 相比,上述示例中要注意两件小事: .parse() 方法处理整个流或字符串,所以不必为语法分析器创建循环; .parse() 同样能灵活地接收一个文件名、一个文件对象,或是众多的类文件对象(一些具有 .read() 方式)。

包:DOM

DOM 是一种 XML 文档的高级树型表示。该模型并非只针对 Python,而是一种普通 XML 模型(请参阅 参考资料以获取进一步信息)。Python 的 DOM 包是基于 SAX 构建的,并且包括在 Python 2.0 的标准 XML 支持里。由于篇幅所限,没有将代码示例加到本文中,但在 XML-SIG 的 "Python/XML HOWTO" 中给出了一个极好的总体描述:

    文档对象模型为 XML 文档指定了树型表示。顶级文档实例是树的根,它只有一个子代,即顶级元素实例;这个元素有表示内容和子元素的子节点,他们也可以有子代,以此类推。定义的函数允许随意遍历结果树,访问元素和属性值,插入和删除节点,以及将树转换回 XML。

    DOM 可以用于修改 XML 文档,因为可以创建一棵 DOM 树,通过添加新节点和来回移动子树来修改这棵树,然后生成一个新的 XML 文档作为输出。您也可以自己构造一棵 DOM 树,然后将它转换成 XML;用这种方法生成 XML 输出比仅将 <tag1>...</tag1> 写入文件的方法更灵活。

使用 xml.dom 模块的语法与早期的文章相比有了一些变动。Python 2.0 中自带的 DOM 实现被称为 xml.dom.minidom ,并提供轻量级和小型版本的 DOM。显然,完整的 XML-SIG 的 DOM 中有些试验性的特性并未被放入 xml.dom.minidom 中,但大家并不会注意到这一点。

生成 DOM 对象很简单;只需:
清单 4: 在 XML 文件中创建 Python DOM 对象

from
         xml.dom.minidom 
    
    import

         parse, parseString
dom1 = parse('mydata.xml') 
    
    # parse an XML file by name

使用 DOM 对象是种非常直接的 OOP 模式的工作。然而,经常在无法立刻简单区分的层级(除了循环列举)中碰到许多类似清单的属性。例如,以下是一段普通的 DOM Python 代码片断:
清单 5: 通过 Python DOM 节点对象的迭代

for
         node 
    
    in
         dom_node.childNodes:
  
    
    if

         node.nodeName == '#text':   
    
    # PCDATA is a kind of node,
    PCDATA = node.nodeValue    
    
    # but not a new subtag
     
     
     elif

         node.nodeName == 'spam':
    spam_node_list.append(node) 
    
    # Create list of <spam> nodes

Python 标准说明文档中有一些更详细的 DOM 示例。我的早期文章中有关使用 DOM 对象的示例(请参阅 参考资料)指出的方向仍然是正确的,但是文章发布后至今,一些方法和属性名称以更改,因此请查阅一下 Python 的说明文档。

模块: pyxie

pyxie 模块是在 Python 标准 XML 支持之上构建的,它为 XML 文档提供了附加的高级接口。 pyxie 将完成两项基本操作:它将 XML 文档转换成一种更易于进行语法分析的基于行的格式;并且它提供了将 XML 文档当作可操作树处理的方法。 pyxie 所使用的基于行的 PYX 格式是不受语言限制的,其工具适用于几种语言。总之,文档的 PYX 表示与其 XML 表示相比,更易于使用常见的基于行的文本处理工具进行处理,如 grep、sed、awk、bash、perl,或标准 python 模块,如 string 和 re 。根据结果,从 XML 转换到 PYX 可能节省许多工作。

pyxie 将 XML 文档当作树处理的概念与 DOM 中的思路相似。由于 DOM 标准得到许多编程语言的广泛支持,那么如果 XML 文档的树型表示是必需的,大多数程序员会使用 DOM 标准而非 pyxie 。

更多模块: xml_pickle 和 xml_objectify

我自行开发了处理 XML 的高级模块,称为 xml_pickle 和 xml_objectify 。我还在其它地方写过许多类似模块(请参阅 参考资料),在此不必做过多的介绍。当你“用 Python 思考”而不是“用 XML 思考”时,这些模块非常有用。特别是 xml_objectify 自身对程序员隐藏了几乎所有的 XML 线索,使您在程序中充分使用 Python “原始”对象。实际的 XML 数据格式几乎被抽象得不可见。同样, xml_pickle 使 Python 程序员以“原始” Python 对象开始,该对象的数据可以来源于任何源代码,然后把它们(连续地)放入其他用户以后可能需要的 XML 格式。

Python 相关文章推荐
python翻译软件实现代码(使用google api完成)
Nov 26 Python
Python中设置变量作为默认值时容易遇到的错误
Apr 03 Python
Python实现对字符串的加密解密方法示例
Apr 29 Python
详解python OpenCV学习笔记之直方图均衡化
Feb 08 Python
Python小白必备的8个最常用的内置函数(推荐)
Apr 03 Python
Python3使用Matplotlib 绘制精美的数学函数图形
Apr 11 Python
pytorch实现Tensor变量之间的转换
Feb 17 Python
Django基于客户端下载文件实现方法
Apr 21 Python
Python读取yaml文件的详细教程
Jul 21 Python
Django crontab定时任务模块操作方法解析
Sep 10 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
Sep 30 Python
python爬虫爬取某网站视频的示例代码
Feb 20 Python
Python中的模块和包概念介绍
Apr 13 #Python
Python多线程编程简单介绍
Apr 13 #Python
Python中的面向对象编程详解(下)
Apr 13 #Python
简单介绍利用TK在Python下进行GUI编程的教程
Apr 13 #Python
Python中的面向对象编程详解(上)
Apr 13 #Python
进一步理解Python中的函数编程
Apr 13 #Python
Python中的异常处理简明介绍
Apr 13 #Python
You might like
PHP版自动生成文章摘要
2008/07/23 PHP
PHP imagegrabscreen和imagegrabwindow(截取网站缩略图)的实例代码
2013/11/07 PHP
去除php注释和去除空格函数分享
2014/03/13 PHP
php微信公众号开发(3)php实现简单微信文本通讯
2016/12/15 PHP
thinkphp5修改view到根目录实例方法
2019/07/02 PHP
jQuery中选择器小问题(新人难免遇到)
2014/03/31 Javascript
JS实现选中当前菜单后高亮显示的导航条效果
2015/10/15 Javascript
在JavaScript中模拟类(class)及类的继承关系
2016/05/20 Javascript
对Js OOP编程 创建对象的一些全面理解
2016/07/26 Javascript
js获取腾讯视频ID的方法
2016/10/03 Javascript
JavaScript 轮播图和自定义滚动条配合鼠标滚轮分享代码贴
2016/10/28 Javascript
浅谈JS函数定义方式的区别
2016/10/30 Javascript
JS请求servlet功能示例
2017/06/01 Javascript
bootstrap switch开关组件使用方法详解
2017/08/22 Javascript
JavaScript判断日期时间差的实例代码
2018/03/01 Javascript
解决Layui中layer报错的问题
2019/09/03 Javascript
es6数组includes()用法实例分析
2020/04/18 Javascript
基于JQuery和DWR实现异步数据传递
2020/10/16 jQuery
Python中使用tarfile压缩、解压tar归档文件示例
2015/04/05 Python
在Python中用keys()方法返回字典键的教程
2015/05/21 Python
在Django的上下文中设置变量的方法
2015/07/20 Python
python一键升级所有pip package的方法
2017/01/16 Python
基于python实现学生管理系统
2018/10/17 Python
Python的垃圾回收机制详解
2019/08/28 Python
如何使用Python多线程测试并发漏洞
2019/12/18 Python
python 解决tqdm模块不能单行显示的问题
2020/02/19 Python
Python模拟登录和登录跳转的参考示例
2020/10/30 Python
CSS 说明横向进度条最后显示文字的实现代码
2020/11/10 HTML / CSS
VELTRA台湾:世界自由行专家
2017/08/15 全球购物
实习生的自我鉴定范文欣赏
2013/11/20 职场文书
数控专业应届生求职信
2013/11/27 职场文书
校园绿化美化方案
2014/06/08 职场文书
学习优秀党务工作者先进事迹材料思想报告
2014/09/17 职场文书
《游戏王:大师决斗》新活动上线 若无符合卡组可免费租用
2022/04/13 其他游戏
MySQL 原理与优化之原数据锁的应用
2022/08/14 MySQL
go goth封装第三方认证库示例详解
2022/08/14 Golang