Python XML解析
2017-07-03 21:28
281 查看
xml 是一种扩展标记语言,实际开发中应用也比较广泛,经常用来在服务端与客户端间进行数据传输。下面我们来一起看下 python 中对 xml 的解析
1.python 解析 xml 的三种方式
python中有三种方法解析xml,分别为:SAX、DOM、ElementTree,建议使用第三种 ElementTree 解析 xml。
SAX用事件驱动模型,通过在解析XML的过程中触发对应的事件并调用用户定义的回调函数来处理XML文件。SAX是一种基于事件驱动的API,使用SAX解析XML会涉及到两个部分:解析器和事件处理器,解析器主要用于解析XML数据,并向事件处理器发送事件(startElement、endElement、characters等),而事件处理器主要用于对触发事件后作响应,对传递的XML数据进行处理。
优点:SAX使用流来读取xml数据,效率快,占用内存少
缺点:需要用户实现回调函数(Handler)
DOM是一次性将xml数据全部读取并解析成一个树放到内存中,通过对树的操作来操作XML。在解析时,一次性读取整个xml文档并把文档中所有的元素存放到内存中的一个树结构中,然后利用DOM提供的函数来读取或修改文档的内容和结构
优点:使用DOM的好处是不用对状态进行追踪,因为每一个节点都知道谁是它的父节点,谁是它的子节点
缺点:一次性将xml数据全部读取映射到内存中的树,效率低、占用内存
ElementTree类似一个轻量级的DOM,具有方便友好的API,代码可用性好,速度快,消耗内存少,推荐使用。
下面我们通过一个案例,分别用这三种方式来解析xml,看下每种方式是如何操作的。
有一个people.xml文件,内容如下
解析people文件中的内容,解析完成后将数据封装到一个Person对象中然后在控制台打印,打印时分别按年龄升序和按中文降序。Person 类如下
2.SAX 解析
sax 解析需要继承ContentHandler并重写其中的方法,ContentHandler类中常用方法如下
sax 模块常用方法
代码:
运行结果:
3.DOM 解析
运行结果与SAX相同
4.ElementTree
ElementTree 在 Python 中有两种实现
一种是纯 Python 实现:xml.etree.ElementTree
另一种是 C 语言实现:xml.etree.cElementTree
建议使用 C 语言 实现的 ElementTree,因为它速度更快,占用内存更少
在程序中导入模块时这样写(如果C语言实现的不能使用再使用纯Python实现的)
ElementTree 中 常用方法
示例:
运行结果:
ElementTree 中 常用属性
示例
运行结果:
ElementTree 的常用方法及属性我们了解后,接着实现我们最开始的案例,代码如下,运行结果与 SAX 相同
1.python 解析 xml 的三种方式
python中有三种方法解析xml,分别为:SAX、DOM、ElementTree,建议使用第三种 ElementTree 解析 xml。
SAX用事件驱动模型,通过在解析XML的过程中触发对应的事件并调用用户定义的回调函数来处理XML文件。SAX是一种基于事件驱动的API,使用SAX解析XML会涉及到两个部分:解析器和事件处理器,解析器主要用于解析XML数据,并向事件处理器发送事件(startElement、endElement、characters等),而事件处理器主要用于对触发事件后作响应,对传递的XML数据进行处理。
优点:SAX使用流来读取xml数据,效率快,占用内存少
缺点:需要用户实现回调函数(Handler)
DOM是一次性将xml数据全部读取并解析成一个树放到内存中,通过对树的操作来操作XML。在解析时,一次性读取整个xml文档并把文档中所有的元素存放到内存中的一个树结构中,然后利用DOM提供的函数来读取或修改文档的内容和结构
优点:使用DOM的好处是不用对状态进行追踪,因为每一个节点都知道谁是它的父节点,谁是它的子节点
缺点:一次性将xml数据全部读取映射到内存中的树,效率低、占用内存
ElementTree类似一个轻量级的DOM,具有方便友好的API,代码可用性好,速度快,消耗内存少,推荐使用。
下面我们通过一个案例,分别用这三种方式来解析xml,看下每种方式是如何操作的。
有一个people.xml文件,内容如下
<?xml version="1.0" encoding="utf-8" ?> <people> <person id="zhangsna"> <name>张三</name> <age>18</age> <tel>18511908765</tel> </person> <person id="lisi"> <name>李四</name> <age>20</age> <tel>15018984728</tel> </person> <person id="wangwu"> <name>王五</name> <age>22</age> <tel>13067894532</tel> </person> <person id="zhaoliu"> <name>赵六</name> <age>23</age> <tel>13067894532</tel> </person> </people>
解析people文件中的内容,解析完成后将数据封装到一个Person对象中然后在控制台打印,打印时分别按年龄升序和按中文降序。Person 类如下
class Person: name=None age=None tel=None def __init__(self,name=None,age=None,tel=None): self.name=name self.age=age self.tel=tel def __repr__(self): # 类似 java 中 的 toString() return '{0:20}{1:<5}{2:15}'.format(self.name, self.age, self.tel)
2.SAX 解析
sax 解析需要继承ContentHandler并重写其中的方法,ContentHandler类中常用方法如下
方法 | 参数 | 作用 |
---|---|---|
startDocument() | self | 文档启动时调用 |
endDocument() | self | 解析器到达文档结尾时调用 |
startElement() | self,name:元素名称,attrs:元素属性 | 遇到XML开始标签时调用 |
endElement() | self,name:元素名称 | 遇到XML结束标签时调用 |
characters | self,content:文本内容 | 读取元素内容时调用 |
方法 | 作用 |
---|---|
make_parser() | 创建一个新的解析器对象并返回 |
parse() | 创建一个 SAX 解析器并解析xml文档 |
parseString() | 创建一个XML解析器并解析xml字符串 |
import xml.sax # 导入sax模块 from Person import Person # 导入Person类 # 继承ContentHandler class PeopleHandler(xml.sax.ContentHandler): # 初始化函数 def __init__(self): self.person = None self.tag = None # 元素开始调用(name:元素名称,attrs:元素属性) def startElement(self, name, attrs): self.tag = name if name == 'person': self.person = Person() # 元素结束调用(name:元素名称) def endElement(self, name): if name == 'person': global people # 引用外部的全局变量 people.append(self.person) self.person = None self.tag = None # 读取元素内容时调用(content:文本内容) def characters(self, content): if "name" == self.tag: self.person.name = content if "age" == self.tag: self.person.age = int(content) if "tel" == self.tag: self.person.tel = content people = [] # 创建一个 XMLReader parser = xml.sax.make_parser() # 关闭命名空间(不验证命名空间) parser.setFeature(xml.sax.handler.feature_namespaces, 0) # 重写 ContextHandler parser.setContentHandler(PeopleHandler()) # 解析xml文档 parser.parse("people.xml") print('{0:20}{1:<5}{2:15}'.format("姓名", "年龄", "手机号")) print("--------------按年龄升序--------------") for p in sorted(people, key=lambda x:x.age, reverse=False): print(p) print("--------------按中文降序--------------") people.sort(key=lambda x:x.name.encode("gbk"), reverse=True) # 中文排序,需要进行编码为gbk或gb2312 for p in people: print(p)
运行结果:
姓名 年龄 手机号 --------------按年龄升序-------------- 张三 18 18511908765 李四 20 15018984728 王五 22 13067894532 赵六 23 13067894532 --------------按中文降序-------------- 赵六 23 13067894532 张三 18 18511908765 王五 22 13067894532 李四 20 15018984728
3.DOM 解析
# 导入模块 from xml.dom.minidom import parse from Person import Person people = [] # 使用minidom解析器打开 XML 文档 domTree = parse("people.xml") # 获取文档元素 collection = domTree.documentElement; # 获取集合中的 person 元素 person = collection.getElementsByTagName("person") for e in person: # 获取所有的id元素的属性 # idAttrs = e.attributes['id'] # print(idAttrs) # 获取所有的name元素 # elements = e.getElementsByTagName("name")[0] # print(elements) # 获取所有的name元素的文本值 # text = e.getElementsByTagName("name")[0].childNodes[0].data; # print(text) name = e.getElementsByTagName("name")[0].childNodes[0].data age = e.getElementsByTagName("age")[0].childNodes[0].data tel = e.getElementsByTagName("tel")[0].childNodes[0].data p = Person(name, age, tel) people.append(p) print('{0:20}{1:<5}{2:15}'.format("姓名", "年龄", "手机号")) print("--------------按年龄升序--------------") for p in sorted(people, key=lambda x:x.age, reverse=False): print(p) print("--------------按中文降序--------------") # 中文排序,需要进行编码为gbk或gb2312 people.sort(key=lambda x:x.name.encode("gbk"), reverse=True) for p in people: print(p)
运行结果与SAX相同
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()类似 |
root = ET.parse("people.xml") print("------------findall()------------") persons1 = root.findall("person") print(persons1) print("----------getiterator()----------") persons2 = root.getiterator("person") print(persons2) print("----------getchildren()----------") for node in persons2: node_child = node.getchildren()[0] print(node_child.tag + " => " + node_child.text)
运行结果:
------------findall()------------ [<Element 'person' at 0x00000000020F02C8>, <Element 'person' at 0x0000000002585908>, <Element 'person' at 0x00000000025A1138>, <Element 'person' at 0x00000000025A1278>] ----------getiterator()---------- [<Element 'person' at 0x00000000020F02C8>, <Element 'person' at 0x0000000002585908>, <Element 'person' at 0x00000000025A1138>, <Element 'person' at 0x00000000025A1278>] ----------getchildren()---------- name => 张三 name => 李四 name => 王五 name => 赵六
ElementTree 中 常用属性
属性 | 作用 |
---|---|
attrib | 获取节点的属性及属性值(以元祖的形式返回) |
tag | 获取节点名称 |
text | 获取节点的文本值 |
root = ET.parse("people.xml") persons = root.findall("person") for node in persons: print(node.attrib) print(node.tag) name = node.find("name") print(name.text)
运行结果:
{'id': 'zhangsna'} person 张三 -------------------- {'id': 'lisi'} person 李四 -------------------- {'id': 'wangwu'} person 王五 -------------------- {'id': 'zhaoliu'} person 赵六 --------------------
ElementTree 的常用方法及属性我们了解后,接着实现我们最开始的案例,代码如下,运行结果与 SAX 相同
from Person import Person try: import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET people = [] # 加载people.xml文件 root = ET.parse("people.xml") # 获取所有person节点 persons = root.findall("person") for node in persons: name = node.find("name").text age = node.find("age").text tel = node.find("tel").text p = Person(name, age, tel) people.append(p) print('{0:20}{1:<5}{2:15}'.format("姓名", "年龄", "手机号")) print("--------------按年龄升序--------------") for p in sorted(people, key=lambda x:x.age, reverse=False): print(p) print("--------------按中文降序--------------") # 中文排序,需要进行编码为gbk或gb2312 people.sort(key=lambda x:x.name.encode("gbk"), reverse=True) for p in people: print(p)
相关文章推荐
- Python的xml.dom.mindom在处理CDATA时候把空格解析为textnode
- python中如何解析xml文档
- python 解析xml
- Python使用ElementTree解析XML
- Python语言解析xml文件
- Python与xml之解析篇
- Python解析XML字符串
- python类库31[使用SAX来解析xml]
- 整理网上python解析xml文件相关资料汇总
- python Python 解析xml文件出现错误xml.parsers.expat.ExpatError: unknown encoding 的解决
- Python解析XML文件
- Python与xml之解析篇
- python 解析XML
- 使用python自带的xml.dom创建和解析xml
- Python实例讲解 -- 解析xml
- 用Python去解析XML报文 V1.1
- [Python]快速解析数据库视图XML配置获取数据库字段说明
- Python 解析XML
- python解析xml文档实例
- Python_使用ElementTree解析xml文件