进一步了解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怎么学好python?
Oct 07 Python
Python查找相似单词的方法
Mar 05 Python
Python函数中的函数(闭包)用法实例
Mar 15 Python
python下如何查询CS反恐精英的服务器信息
Jan 17 Python
Python操作mysql数据库实现增删查改功能的方法
Jan 15 Python
Python多层装饰器用法实例分析
Feb 09 Python
完美解决安装完tensorflow后pip无法使用的问题
Jun 11 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
Jul 04 Python
Python面向对象原理与基础语法详解
Jan 02 Python
python3 实现口罩抽签的功能
Mar 11 Python
DjangoWeb使用Datatable进行后端分页的实现
May 18 Python
利用Python判断整数是否是回文数的3种方法总结
Jul 07 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
Syphon 秘笈
2021/03/03 冲泡冲煮
PHP base64编码后解码乱码的解决办法
2014/06/19 PHP
PHP入门教程之面向对象的特性分析(继承,多态,接口,抽象类,抽象方法等)
2016/09/11 PHP
php变量与数组相互转换的方法(extract与compact)
2016/12/02 PHP
php获取'/'传参的值简单方法
2017/07/13 PHP
PHP架构及原理知识点详解
2019/12/22 PHP
实现复选框全选/全不选切换
2006/12/23 Javascript
document.documentElement &amp;&amp; document.documentElement.scrollTop
2007/12/01 Javascript
Js sort排序使用方法
2011/10/17 Javascript
Javascript级联下拉菜单以及AJAX数据验证核心代码
2013/05/10 Javascript
浅析JavaScript中两种类型的全局对象/函数
2013/12/05 Javascript
NodeJS学习笔记之网络编程
2014/08/03 NodeJs
JS实现鼠标箭头变成一个燃烧烛光效果的方法
2015/02/28 Javascript
jQuery检测输入的字符串包含的中英文的数量
2015/04/17 Javascript
jquery 获取select数组与name数组长度的实现代码
2016/06/20 Javascript
理解JavaScript原型链
2016/10/25 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
2017/05/24 Javascript
使用Vue写一个datepicker的示例
2018/01/27 Javascript
Angular服务Request异步请求的实例讲解
2018/08/13 Javascript
JS中DOM元素的attribute与property属性示例详解
2018/09/04 Javascript
原生javascript自定义input[type=radio]效果示例
2019/08/27 Javascript
js cavans实现静态滚动弹幕
2020/05/21 Javascript
python实现的生成随机迷宫算法核心代码分享(含游戏完整代码)
2014/07/11 Python
Python中optparse模块使用浅析
2015/01/01 Python
详解Python中的日志模块logging
2015/06/19 Python
python使用Matplotlib画饼图
2018/09/25 Python
利用python-docx模块写批量生日邀请函
2019/08/26 Python
Python3实现个位数字和十位数字对调, 其乘积不变
2020/05/03 Python
详解如何用HTML5 Canvas API控制图片的缩放变换
2016/03/22 HTML / CSS
Otel.com:折扣酒店预订
2017/08/24 全球购物
C#里面如何判断一个Object是否是某种类型(如Boolean)?
2016/02/10 面试题
体育教育个人自荐信范文
2013/12/01 职场文书
挂职思想汇报
2013/12/31 职场文书
对外汉语教师推荐信
2015/03/27 职场文书
在MySQL中你成功的避开了所有索引
2022/04/20 MySQL
Hive HQL支持2种查询语句风格
2022/06/25 数据库