进一步了解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系列之教你如何根据图片生成字符画
May 23 Python
python使用Berkeley DB数据库实例
Sep 26 Python
Python字符串、元组、列表、字典互相转换的方法
Jan 23 Python
全面了解python中的类,对象,方法,属性
Sep 11 Python
Python做简单的字符串匹配详解
Mar 21 Python
从CentOS安装完成到生成词云python的实例
Dec 01 Python
详解分布式任务队列Celery使用说明
Nov 29 Python
python gensim使用word2vec词向量处理中文语料的方法
Jul 05 Python
python在openstreetmap地图上绘制路线图的实现
Jul 11 Python
python代码实现将列表中重复元素之间的内容全部滤除
May 22 Python
Python深度学习之实现卷积神经网络
Jun 05 Python
教你用Python matplotlib库制作简单的动画
Jun 11 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
4.与数据库的连接
2006/10/09 PHP
php格式化日期实例分析
2014/11/12 PHP
PHP简单实现记录网站访问量功能示例
2018/06/06 PHP
js form action动态修改方法
2008/11/04 Javascript
鼠标右击事件代码(asp.net后台)
2011/01/27 Javascript
myEvent.js javascript跨浏览器事件框架
2011/10/24 Javascript
js实现鼠标拖动图片并兼容IE/FF火狐/谷歌等主流浏览器
2013/06/06 Javascript
JavaScript版TAB选项卡效果实例
2013/08/16 Javascript
jQuery简单实现隐藏以及显示特效
2015/02/26 Javascript
Bootstrap登陆注册页面开发教程
2016/07/12 Javascript
JS判断是否为JSON对象及是否存在某字段的方法(推荐)
2016/11/29 Javascript
JS实现颜色梯度与渐变效果完整实例
2016/12/30 Javascript
less简单入门(CSS 预处理语言)
2017/03/08 Javascript
vue.js+Echarts开发图表放大缩小功能实例
2017/06/09 Javascript
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
基于javascript中的typeof和类型判断(详解)
2017/10/27 Javascript
Vue cli 引入第三方JS和CSS的常用方法分享
2018/01/20 Javascript
nodeJs实现基于连接池连接mysql的方法示例
2018/02/10 NodeJs
node全局变量__dirname与__filename的区别
2019/01/14 Javascript
Javascript新手入门之字符串拼接与变量的应用
2020/12/03 Javascript
利用Fn.py库在Python中进行函数式编程
2015/04/22 Python
Python中Continue语句的用法的举例详解
2015/05/14 Python
python实现对excel进行数据剔除操作实例
2017/12/07 Python
Python实现去除列表中重复元素的方法小结【4种方法】
2018/04/27 Python
Django项目创建到启动详解(最全最详细)
2019/09/07 Python
python GUI库图形界面开发之PyQt5开发环境配置与基础使用
2020/02/25 Python
浅谈TensorFlow中读取图像数据的三种方式
2020/06/30 Python
CSS3实现内凹圆角的实例代码
2017/05/04 HTML / CSS
纯css实现照片墙3D效果的示例代码
2017/11/13 HTML / CSS
洗煤厂厂长岗位职责
2014/01/03 职场文书
高级工程师英文求职信
2014/03/19 职场文书
基层党组织公开承诺书
2014/03/28 职场文书
说明书格式及范文
2014/05/07 职场文书
工作证明格式及范本
2014/09/12 职场文书
mysq启动失败问题及场景分析
2021/07/15 MySQL
分析SQL窗口函数之取值窗口函数
2022/04/21 Oracle