Python中提供的XML解析方式:
方法 | 特点 |
SAX | SAX解析通过流模式在解析XML的过程中触发对应的事件(start_element、char_data、end_element)并调用用户定义的回调函数来处理XML文件。 |
DOM | 将XML数据在内存中解析成一个树,通过对树的操作来操作XML,占用内存大,解析速度较慢,优点是可以任意遍历树的节点。 |
ElementTree | 类似一个轻量级的DOM。 |
1. DOM 解析
DOM 解析器在解析 XML 文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构中,之后可以利用 DOM 提供的各种函数来读取或修改文档内容和结构,也可以把修改过的内容写入 xml 文件。
from xml.dom.minidom import parse
python 中用 xml.dom.minidom 来解析 xml 文件。
示例xml:students.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE students [
<!ELEMENT students (student)*>
<!ELEMENT student (stuname|stuage|stusex)*>
<!ATTLIST student
id CDATA #REQUIRED>
<!ELEMENT stuname (#PCDATA)>
<!ELEMENT stuage (#PCDATA)>
<!ELEMENT stusex (#PCDATA)>
]>
<students>
<student id="1">
<stuname>张三</stuname>
<stuage>20</stuage>
<stusex>女</stusex>
</student>
<student id="2">
<stuname>李四</stuname>
<stuage>21</stuage>
<stusex>男</stusex>
</student>
</students>
DOM 解析:
from xml.dom.minidom import parse
class Student:
def __init__(self,id=None,name=None,age=None,sex=None):
self.id=id
self.name=name
self.age=age
self.sex=sex
def __repr__(self):
return self.id+'\t'+self.name+'\t'+self.age+'\t'+self.sex
l=[]
domTree=parse("students.xml")
root= domTree.documentElement
students=root.getElementsByTagName("student")
for s in students:
name=s.getElementsByTagName('stuname')[0].childNodes[0].data
age=s.getElementsByTagName('stuage')[0].childNodes[0].data
sex = s.getElementsByTagName('stusex')[0].childNodes[0].data
id=s.getAttribute('id')
stu=Student(id,name,age,sex)
l.append(stu)
for i in l:
print(i)
2. SAX 解析
SAX 是一种基于事件驱动的 API,包括解析器和事件处理器。
解析器负责读取XML文档,并向事件处理器发送事件。而事件处理器则负责对事件作出响应,对传递的XML数据进行处理。
适用场景:
1、对大型文件进行处理;
2、只需要文件的部分内容,或者只需从文件中得到特定信息。
3、想建立自己的对象模型的时候。
sax 解析需要继承 ContentHandler 并重写其中的方法,ContentHandler 类中常用方法如下:
方法 参数 作用
startDocument(self) 文档启动时调用
endDocument(self) 解析器到达文档结尾时调用
startElement(self,name):元素名称,attrs:元素属性 遇到XML开始标签时调用
endElement(self,name):元素名称 遇到XML结束标签时调用
characters(self,content):文本内容 读取元素内容时调用
sax 模块常用方法
方法 作用
make_parser() 创建一个新的解析器对象并返回
parse() 创建一个 SAX 解析器并解析xml文档
parseString() 创建一个XML解析器并解析xml字符串
from xml.sax import parse
from xml.sax import ContentHandler
from xml.sax import parse, ContentHandler
class Student:
def __init__(self, id=None, name=None, age=None, sex=None):
self.id = id
self.name = name
self.age = age
self.sex = sex
def __repr__(self):
return self.id + '\t' + self.name + '\t\t' + self.age + '\t' + self.sex
stulist=[]
class SaxParser(ContentHandler):
def __init__(self,name=None):
self.name=name
self.stu=None
def startElement(self, name, attrs):
if name =='student':
self.stu=Student()
self.stu.id=attrs['id']
self.name=name
def characters(self, content):
if self.name =='stuname':
self.stu.name=content
elif self.name=='stuage':
self.stu.age=content
elif self.name=='stusex':
self.stu.sex=content
def endElement(self, name):
if name =='student':
stulist.append(self.stu)
self.name=None
parse('students.xml',SaxParser())
for i in stulist:
print(i)
3. ElementTree 解析
ElementTree 在 Python 中有两种实现
一种是纯 Python 实现:xml.etree.ElementTree
另一种是 C 语言实现:xml.etree.cElementTree
建议使用 C 语言 实现的 ElementTree,因为它速度更快,占用内存更少
在程序中导入模块时这样写(如果C语言实现的不能使用再使用纯Python实现的)
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
ElementTree 中 常用方法
方法 作用
parse(xmlfile) 加载xml文件
fromstring(xmltext) 加载xml文件
findall() 获取指定的所有节点
find() 获取指定的节点
getchildren() 获取儿子节点
getiterator() 获取指定的所有节点,与findall()类似
属性 作用
attrib 获取节点的属性及属性值(以元祖的形式返回)
tag 获取节点名称
text 获取节点的文本值
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
class Student:
def __init__(self, id=None, name=None, age=None, sex=None):
self.id = id
self.name = name
self.age = age
self.sex = sex
def __repr__(self):
return self.id + '\t' + self.name + '\t\t' + self.age + '\t' + self.sex
stulist=[]
def test():
tree=ET.parse('students.xml')
students=tree.findall('student')
for i in students:
stu=Student()
children=i.getchildren()
stu.name= children[0].text
stu.age= children[1].text
stu.sex= children[2].text
stu.id= i.attrib['id']
stulist.append(stu)
test()
for j in stulist:
print(j)