XML解析

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 男

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值