Python 3 XML 解析

XML 指可扩展标记语言(e X tensible M arkup L anguage)

XML

XML 是当下最流行的用来传输和存储数据的格式之一,仅次于 JSON

XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识

XML 也是元标记语言,可以用于定义其它与特定领域有关的、语义的、结构化的标记语言的句法语言

常见的 XML 编程接口有 DOM 和 SAX,这两种接口处理 XML 文件的方式不同,当然使用场合也不同

Python 与 XML

Python 提供了对 XML 的良好支持,官方内置了几个模块用于处理 XML 文档

Python 官方提供了三种方法来解析 XML :SAX 、DOM 、ElementTree

  1. SAX ( Simple API for XML )

    SAX 使用事件驱动模型,通过在解析 XML 的过程中触发一个个的事件并调用用户定义的回调函数来处理 XML 数据

    Python 通过 xml.sax 模块提供了对 SAX 解析器的支持

  2. DOM ( Document Object Model )

    DOM,及文档对象模型,将 XML 数据在内存中解析成一个树,通过对树的操作来操作 XML

    Python 通过 xml.dom 模块提供了对 XML DOM 解析器的支持

  3. ElementTree ( 元素树 )

    ElementTree 就像一个轻量级的 DOM,具有方便友好的 API

    代码可用性好,速度快,消耗内存少

    Python 通过 xml.etree.ElementTree 模块提供了对 ElementTree 解析方法的支持

三者比较

  1. DOM 需要将 XML 数据映射到内存中的树,一是比较慢,二是比较耗内存
  2. SAX 流式读取 XML 文件,比较快,占用内存少,但需要用户实现回调函数 ( handler )
  3. ElementTree 就像一个轻量级的 DOM,具有方便友好的 API,代码可用性好,速度快,消耗内存少

范例 XML 文件

下面是本章接下来要解析的 XML 文件内容,你可点击 2018-1-movies.xml 查看详情

<?xml version="1.0" encoding="UTF-8"?>
<collection shelf="2018年1月上映电影">
<movie title="勇敢者游戏:决战丛林">
   <type>动作 / 奇幻 / 冒险</type>
   <country>USA</country>
   <date>2018-01-12</date>
   <language>英语</language>
   <stars>7.2</stars>
   <description>讲述了四名性格迥异的高中生意外穿越到险象环生的勇敢者游戏中,变身成为与自身性格外貌截然不同的游戏角色</description>
</movie>
<movie title="无问西东">
   <type>剧情 / 爱情 / 战争</type>
   <country>China</country>
   <date>2018-01-12</date>
   <language>普通话</language>
   <stars>7.4</stars>
   <description>如果提前了解了你所要面对的人生,你是否还会有勇气前来?吴岭澜、沈光耀、王敏佳、陈鹏、张果果,几个年轻人满怀诸多渴望,在四个非同凡响的时空中一路前行</description>
</movie>
<movie title="前任3:再见前任">
   <type>喜剧 / 爱情</type>
   <country>China</country>
   <date>2017-12-29</date>
   <language>普通话</language>
   <stars>5.7</stars>
   <description>两对恋人分手后的故事:是再次相见?还是再也不见</description>
</movie>
<movie title="太空救援 Салют-7">
   <type>动作 / 冒险</type>
   <country>China</country>
   <date>2017-12-29</date>
   <language>russia</language>
   <stars>7.7</stars>
   <description>这不是一部《地心引力》那样的「科幻片」,它更像《阿波罗13号》,是一部「基于真实事件改编」而成的太空题材电影</description>
</movie>
</collection>

Python 使用 SAX 解析 xml

SAX 是一种基于事件驱动的 API

使用 SAX 解析 XML 文档牵涉到两个部分: 解析器和事件处理器

  1. 解析器负责读取 XML 文档,并向事件处理器发送事件, 如元素开始跟元素结束事件
  2. 而事件处理器则负责对事件作出相应,对传递的 XML 数据进行处理

    1. 对大型文件进行处理;
    2. 只需要文件的部分内容,或者只需从文件中得到特定信息
    3. 想建立自己的对象模型的时候

导入模块

import xml.sax

ContentHandler 类

characters(content) 方法

调用时机

从行开始,遇到标签之前,存在字符,content 的值为这些字符串

从一个标签,遇到下一个标签之前, 存在字符,content 的值为这些字符串

从一个标签,遇到行结束符之前,存在字符,content的值为这些字符串

标签可以是开始标签,也可以是结束标签

下表列出了 ContentHandler 类的其它些方法

方法 说明
startDocument() 文档启动的时候调用
endDocument() 解析器到达文档结尾时调用
startElement(name, attrs) 遇到 XML 开始标签时调用
name 是标签的名字,attrs 是标签的属性值字典
endElement(name) 遇到 XML 结束标签时调用

make_parser() 方法

make_parser() 方法创建并返回一个新的解析器对象

xml.sax.make_parser( [parser_list] )

参数说明

参数 说明
parser_list 可选参数,解析器列表

parser() 方法

parser() 方法创建一个 SAX 解析器并解析 xml 文档

xml.sax.parse( xmlfile, contenthandler[, errorhandler])

参数说明

参数 说明
xmlfile xml 文件名
contenthandler 一个 ContentHandler 的对象
errorhandler 可选,errorhandler 必须是一个 SAX ErrorHandler 对象

parseString() 方法

parseString() 方法创建一个 XML 解析器并解析 xml 字符串

xml.sax.parseString(xmlstring, contenthandler[, errorhandler])

参数说明

参数 说明
xmlstring xml 字符串
contenthandler 一个 ContentHandler 的对象
errorhandler 可选,errorhandler 必须是一个 SAX ErrorHandler 对象

范例

下面的代码使用 xml.sax 模块来解析 XML 数据

#!/usr/bin/python

import xml.sax

class MovieHandler( xml.sax.ContentHandler ):
   def __init__(self):
      self.CurrentData = ""
      self.type = ""
      self.country = ""
      self.date = ""
      self.language = ""
      self.stars = ""
      self.description = ""

   # 元素开始事件处理
   def startElement(self, tag, attributes):
      self.CurrentData = tag
      if tag == "movie":
         print ("*****Movie*****")
         title = attributes["title"]
         print ("Title:", title)

   # 元素结束事件处理
   def endElement(self, tag):
      if self.CurrentData == "type":
         print ("Type:", self.type )
      elif self.CurrentData == "country":
         print ("Country:", self.country )
      elif self.CurrentData == "date":
         print ("Date:", self.date )
      elif self.CurrentData == "language":
         print ("Language:", self.language )
      elif self.CurrentData == "stars":
         print ("Stars:", self.stars )
      elif self.CurrentData == "description":
         print ("Description:", self.description )
      self.CurrentData = ""

   # 内容事件处理
   def characters(self, content):
      if self.CurrentData == "type":
         self.type = content
      elif self.CurrentData == "country":
         self.country = content
      elif self.CurrentData == "date":
         self.date = content
      elif self.CurrentData == "language":
         self.language = content
      elif self.CurrentData == "stars":
         self.stars = content
      elif self.CurrentData == "description":
         self.description = content

if ( __name__ == "__main__"):

   # 创建一个 XMLReader
   parser = xml.sax.make_parser()
   # turn off namepsaces
   parser.setFeature(xml.sax.handler.feature_namespaces, 0)

   # 重写 ContextHandler
   Handler = MovieHandler()
   parser.setContentHandler( Handler )

   parser.parse("2018-1-movies.xml")

运行以上 Python 代码,输出结果如下

$ python main.py 
*****Movie*****
Title: 勇敢者游戏:决战丛林
Type: 动作 / 奇幻 / 冒险
Country: USA
Date: 2018-01-12
Language: 英语
Stars: 7.2
Description: 讲述了四名性格迥异的高中生意外穿越到险象环生的勇敢者游戏中,变身成为与自身性格外貌截然不同的游戏角色
*****Movie*****
Title: 无问西东
Type: 剧情 / 爱情 / 战争
Country: China
Date: 2018-01-12
Language: 普通话
Stars: 7.4
Description: 如果提前了解了你所要面对的人生,你是否还会有勇气前来?吴岭澜、沈光耀、王敏佳、陈鹏、张果果,几个年轻人满怀诸多渴望,在四个非同凡响的时空中一路前行
*****Movie*****
Title: 前任3:再见前任
Type: 喜剧 / 爱情
Country: China
Date: 2017-12-29
Language: 普通话
Stars: 5.7
Description: 两对恋人分手后的故事:是再次相见?还是再也不见
*****Movie*****
Title: 太空救援 Салют-7
Type: 动作 / 冒险
Country: China
Date: 2017-12-29
Language: russia
Stars: 7.7
Description: 这不是一部《地心引力》那样的「科幻片」,它更像《阿波罗13号》,是一部「基于真实事件改编」而成的太空题材电

完整的 SAX API 文档可以访问Python SAX APIs

Python 使用 xml.dom 解析 xml

DOM (Document Object Model,简称 DOM,中文文件对象模型) 是 W3C 组织推荐的处理可扩展置标语言的标准编程接口

使用 DOM 的解析器解析一个 XML 文档时,会一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里

然后就可以利用 DOM 提供的不同的函数来读取或修改文档的内容和结构

最后也可以把修改过的内容写入 xml 文件

Python 通过 xml.dom.minidom 提供了使用 DOM 解析 XML 的能力

#!/usr/bin/python

from xml.dom.minidom import parse
import xml.dom.minidom

# 使用 minidom 解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse("2018-1-movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
   print ("Root element : %s" % collection.getAttribute("shelf"))

# 在集合中获取所有电影
movies = collection.getElementsByTagName("movie")

# 打印每部电影的详细信息
for movie in movies:
   print ("*****Movie*****")
   if movie.hasAttribute("title"):
      print ("Title: %s" % movie.getAttribute("title"))

   country = movie.getElementsByTagName('country')[0]
   print ("Country: %s" % country.childNodes[0].data )
   date = movie.getElementsByTagName('date')[0] 
   print ("Date: %s" % date.childNodes[0].data )
   language = movie.getElementsByTagName('language')[0]
   print ("Rating: %s" % language.childNodes[0].data )
   description = movie.getElementsByTagName('description')[0]
   print ("Description: %s" % description.childNodes[0].data )

运行以上 Python 代码,输出结果如下

$ python main.py        
Root element : 2018年1月上映电影
*****Movie*****
Title: 勇敢者游戏:决战丛林
Country: USA
Date: 2018-01-12
Rating: 英语
Description: 讲述了四名性格迥异的高中生意外穿越到险象环生的勇敢者游戏中,变身成为与自身性格外貌截然不同的游戏角色
*****Movie*****
Title: 无问西东
Country: China
Date: 2018-01-12
Rating: 普通话
Description: 如果提前了解了你所要面对的人生,你是否还会有勇气前来?吴岭澜、沈光耀、王敏佳、陈鹏、张果果,几个年轻人满怀诸多渴望,在四个非同凡响的时空中一路前行
*****Movie*****
Title: 前任3:再见前任
Country: China
Date: 2017-12-29
Rating: 普通话
Description: 两对恋人分手后的故事:是再次相见?还是再也不见
*****Movie*****
Title: 太空救援 Салют-7
Country: China
Date: 2017-12-29
Rating: russia
Description: 这不是一部《地心引力》那样的「科幻片」,它更像《阿波罗13号》,是一部「基于真实事件改编」而成的太空题材电

完整的 DOM API 文档可以访问Python DOM APIs

Python3 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.