1 XML
XML 指可扩展标记语言(eXtensible Markup Language)。 你可以通过本站学习
XML 被设计用来传输和存储数据。
XML是一套定义语义标记的规则:
配置文件
1.标签成对出现
2.区分大小写
3.标签要正确嵌套
4.开始部分
5.只能有一个根节点
6.节点可以有属性
DTD
(Document Type Definition):约束XML文件的节点
下面是一个简单的XML文件(文件名:xml.xml)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE students [
<!ELEMENT students (student+)>
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
]>
<students> #根节点
<student id="1">
<name>张三</name>
<age>19</age>
<sex>男</sex>
</student>
<student id="2">
<name>李四</name>
<age>22</age>
<sex>男</sex>
</student>
</students>
python有三种方法解析XML文件,DOM,SAX以及ElementTree。
2 DOM
dom(文档对象模型) :将XML数据在内存中解析成一个树,通过对树的操作来操作XML。
一个 DOM 的解析器在解析一个 XML 文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后你可以利用DOM 提供的不同的函数来读取或修改文档的内容和结构,也可以把修改过的内容写入xml文件。
下面我们尝试解析上面xml文件:
#mxl.dom.minidom 模块被用来处理xml文件,所以要先引入
from xml.dom.minidom import parse
# 用于打开一个xml文件,并将这个文件对象赋给stus变量
stus=parse("xml.xml")
#documentElement用于得到stus对象的文档元素,并把获得的对象给root
root=stus.documentElement
#获取root对象中所有节点student
students=root.getElementsByTagName("student")
#定义一个方法
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):
if len(self.name.encode('UTF-8'))<=8:
return self.id+'\t'+self.name+'\t\t'+self.age+'\t'+self.sex
else:
return self.id + '\t' + self.name + '\t' + self.age + '\t' + self.sex
stulist1 = []
for s in students:
id = s.getAttribute("id") #获取根节点中每个子节点student的属性id值
name = s.getElementsByTagName("name")[0].childNodes[0].data #s.getElementsByTagName("name")获取每个student中标签为name的对象集合(只是一个对象),childNodes 返回节点的子节点集合
age = s.getElementsByTagName("age")[0].childNodes[0].data
sex = s.getElementsByTagName("sex")[0].childNodes[0].data
stu = Student(id, name, age, sex)
print(stu)
stulist1.append(stu)
print(stulist1 )
结果:
[1 张三 19 男, 2 李四 22 男]
3 SAX
SAX是一种基于事件驱动的API。
利用SAX解析XML文档牵涉到两个部分:解析器和事件处理器。
解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件;
而事件处理器则负责对事件作出相应,对传递的XML数据进行处理。
适用于下列一些情况:
1、对大型文件进行处理;
2、只需要文件的部分内容,或者只需从文件中得到特定信息。(不会在内存中加载整个文档,只会根据自己编写的事件保存数据)
3、想建立自己的对象模型的时候。
方法 参数 作用
startDocument() self 文档启动时调用
endDocument() self 解析器到达文档结尾时调用
startElement() self,name,attrs 遇到XML开始标签时调用
endElement() self,name: 遇到XML结束标签时调用
charactersself() self.content: characters(content)方法
characters(content)方法
调用时机:
从行开始,遇到标签之前,存在字符,content的值为这些字符串。
从一个标签,遇到下一个标签之前, 存在字符,content的值为这些字符串。
从一个标签,遇到行结束符之前,存在字符,content的值为这些字符串。
标签可以是开始标签,也可以是结束标签。
sax 模块常用方法
方法 作用
make_parser() 创建一个新的解析器对象并返回
parse() 创建一个 SAX 解析器并解析xml文档
parseString() 创建一个XML解析器并解析xml字符串
下面用SAX解析xml文件:
from xml.sax import parse #导入parse
from xml.sax.handler import ContentHandler #导入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):
if len(self.name.encode('UTF-8'))<=8:
return self.id+'\t'+self.name+'\t\t'+self.age+'\t'+self.sex
else:
return self.id + '\t' + self.name + '\t' + self.age + '\t' + self.sex
stulist=[]
class saxParse(ContentHandler): #重写一个SAX子类,继承ContentHandler,并重写其中的一些方法
def __init__(self,name=None):
self.name=name
self.stu=None
def startDocument(self):
print('文件开始读取')
def startElement(self,name,attrs):
if name=='student':
self.stu=Student()
self.stu.id = attrs['id']
self.name=name
def endElement(self,name):
if name=='student':
stulist.append(self.stu)
self.name=None
def characters(self, content):
if self.name=="name":
self.stu.name=content
elif self.name=="age":
self.stu.age = content
elif self.name == "sex":
self.stu.sex = content
def endDocument(self):
print('文件结束')
parse("xml.xml",saxParse())
for i in stulist:
print(i)
结果:
文件开始读取
文件结束
1 张三 19 男
2 李四 22 男
4 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 获取节点的属性及属性值(以元祖的形式返回)stu.attrib 返回dict
tag 获取节点名称
text 获取节点的文本值
我们也用ElementTree解析方法xml文件:
# 导入树的解析方法
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):
if len(self.name.encode('UTF-8'))<=8:
return self.id+'\t'+self.name+'\t\t'+self.age+'\t'+self.sex
else:
return self.id + '\t' + self.name + '\t' + self.age + '\t' + self.sex
stulist= []
def test():
tree=ET.parse("xml.xml")
students=tree.findall('student') #找到文件里面所有的studend节点
for stu in students:
student = Student()
children=stu.getchildren() #返回一个列表
student.id=stu.attrib['id'] #通过字典键取ID的值
student.name = children[0].text
student.age = children[1].text
student.sex = children[2].text
stulist.append(student)
test()
for i in stulist:
print(i)
结果:
1 张三 19 男
2 李四 22 男