Python解析XML文件
三种方式
- SAX(simple api for xml)
- DOM(Document Object Moedl)
- ElementTree(元素树)
需要解析的xml文件:
<?xml version="1.0" encoding="utf-8" ?>
<books>
<book id="j01">
<name>java</name>
<price>100</price>
<author>jams</author>
</book>
<book id="c01">
<name>C</name>
<price>200</price>
<author>bart</author>
</book>
<book id="py01">
<name>python</name>
<price>300</price>
<author>lisa</author>
</book>
<book id="c#01">
<name>C#</name>
<price>200</price>
<author>maggie</author>
</book>
</books>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
SAX
事件驱动模式
- 解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件;
- 而事件处理器则负责对事件作出相应,对传递的XML数据进行处理。
- 解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件,而事件处理器则负责对事件作出相应,对传递的XML数据进行处理。
1、对大型文件进行处理;
2、只需要文件的部分内容,或者只需从文件中得到特定信息。
3、想建立自己的对象模型的时候。
在python中使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler。
ContentHandler类方法介绍
characters(content)方法
调用时机:- 从行开始,遇到标签之前,存在字符,content的值为这些字符串。
- 从一个标签,遇到下一个标签之前, 存在字符,content的值为这些字符串。
- 从一个标签,遇到行结束符之前,存在字符,content的值为这些字符串。
- 标签可以是开始标签,也可以是结束标签。
startDocument()方法
文档启动的时候调用。endDocument()方法
解析器到达文档结尾时调用。startElement(name, attrs)方法
遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。endElement(name)方法
遇到XML结束标签时调用。
- make_parser方法
以下方法创建一个新的解析器对象并返回。
xml.sax.make_parser( [parser_list] )
参数说明:
- parser_list
- 可选参数,解析器列表
- 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 文件对象
import xml.sax
# 继承 xml.sax.ContentHandler 对象
# 实现原理,当开始解析标签的时候调用startElement方法
# 解析标签内容的时候调用characters方法
# 解析完标签之后调用endElement方法
class BookHandler(xml.sax.ContentHandler):
# 构造函数
def __init__(self):
self.CurrentData = ""
self.name = ""
self.price = ""
self.author = ""
# 元素开始事件处理
def startElement(self,tag,attributes):
self.CurrentData = tag
if tag == "book":
print("===%s (id= %s)"%(tag,attributes["id"]))
# 元素内容处理事件
def characters(self,content):
if self.CurrentData == "name":
self.name = content
elif self.CurrentData == "price":
self.price = content
elif self.CurrentData == "author":
self.author = content
# 元素结束事件处理
def endElement(self,tag):
if self.CurrentData == "name":
print("name:"+self.name)
elif self.CurrentData == "price":
print("price:"+self.price)
elif self.CurrentData == "author":
print("author:"+self.author)
self.CurrentData = ""
# main 方法
if( __name__ == "__main__" ):
# 创建一个XMLReader
parser = xml.sax.make_parser()
# 关闭命名空间
parser.setFeature(xml.sax.handler.feature_namespaces,0)
# 重写 ContextHandler,即自定义的类赋值给Handler
Handler = BookHandler()
# 设置解析器
parser.setContentHandler(Handler)
# 开始解析 xml 文件
parser.parse("book.xml")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
输出结果:
===book (id= j01)
name:java
price:100
author:jams
===book (id= c01)
name:C
price:200
author:bart
===book (id= py01)
name:python
price:300
author:lisa
===book (id= c#01)
name:C#
price:200
author:maggie
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
DOM
将 xml 文件在内存中解析成一个 树,通过对树的遍历操作xml
文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口。
一个 DOM 的解析器在解析一个 XML 文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后
你可以利用DOM 提供的不同的函数来读取或修改文档的内容和结构,也可以把修改过的内容写入xml文件。
# 导解析器的包
from xml.dom.minidom import parse
# 导 minidom 的包
import xml.dom.minidom
# 解析器解析整个xml文档
DOMTree = parse("book.xml")
# 获得根节点
root = DOMTree.documentElement
print("root element is:%s"%(root))
# 获得所有 book 节点
books = DOMTree.getElementsByTagName("book")
# 遍历
for book in books :
# 打印 book 节点的 id 属性
print("***book id=%s"%(book.getAttribute("id")))
# 获得 name 属性的第一个元素对象,获得该元素对象的第一个子节点对象的 data
name = book.getElementsByTagName("name")[0].childNodes[0].data
print("name:%s"%(name))
price = book.getElementsByTagName("price")[0].childNodes[0].data
print("price:%s"%(price))
author = book.getElementsByTagName("author")[0].childNodes[0].data
print("author:%s"%(author))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
输出结果:
root element is:<DOM Element: books at 0x229a470>
***book id=j01
name:java
price:100
author:jams
***book id=c01
name:C
price:200
author:bart
***book id=py01
name:python
price:300
author:lisa
***book id=c#01
name:C#
price:200
author:maggie
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
ElementTree
类似一个轻量级的dom 消耗内存少
- parse(<路径>):
返回一个xml.etree.ElementTree.ElementTree对象
- findall(“./<标签>”):
返回一个list对象 ,存放着指定标签的xml.etree.ElementTree.Element元素对象
# 从xml.etree 模块中 导入ElementTree并取别名为 et
from xml.etree import ElementTree as et
# 解析xml文件
per = et.parse("book.xml")
# 从哪个标签开始解析
p = per.findall("./book")
# 开始遍历 对应的标签拥有的子标签
for item in p:
for node in item:
print(node.tag+":"+node.text)
print("******************")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
输出结果:
name:java
price:100
author:jams
******************
name:C
price:200
author:bart
******************
name:python
price:300
author:lisa
******************
name:C#
price:200
author:maggie
******************