Python 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
-
SAX ( Simple API for XML )
SAX 使用事件驱动模型,通过在解析 XML 的过程中触发一个个的事件并调用用户定义的回调函数来处理 XML 数据
Python 通过
xml.sax
模块提供了对 SAX 解析器的支持 -
DOM ( Document Object Model )
DOM,及文档对象模型,将 XML 数据在内存中解析成一个树,通过对树的操作来操作 XML
Python 通过
xml.dom
模块提供了对 XML DOM 解析器的支持 -
ElementTree ( 元素树 )
ElementTree 就像一个轻量级的 DOM,具有方便友好的 API
代码可用性好,速度快,消耗内存少
Python 通过
xml.etree.ElementTree
模块提供了对 ElementTree 解析方法的支持
三者比较
- DOM 需要将 XML 数据映射到内存中的树,一是比较慢,二是比较耗内存
- SAX 流式读取 XML 文件,比较快,占用内存少,但需要用户实现回调函数 ( handler )
- 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 文档牵涉到两个部分: 解析器和事件处理器
- 解析器负责读取 XML 文档,并向事件处理器发送事件, 如元素开始跟元素结束事件
-
而事件处理器则负责对事件作出相应,对传递的 XML 数据进行处理
- 对大型文件进行处理;
- 只需要文件的部分内容,或者只需从文件中得到特定信息
- 想建立自己的对象模型的时候
导入模块
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 # -*- coding: UTF-8 -*- 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 # -*- coding: UTF-8 -*- 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