Python XML解析之ElementTree
API名称:
from xml.etree import ElementTree as ET
概念定义:
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
我们把<country>xxx</contry>这种结构称为一个element,country称作element的tag,<></>之间的内容称作element的text或data,<>中的name称作element的attrib,而整个XML树被称作ElementTree。
element是一个名为xml.etree.ElementTree.Element的类,其描述为:
class xml.etree.ElementTree.Element(tag, attrib={}, **extra)
此类的所有属性和方法查看:
https://docs.python.org/2/library/xml.etree.elementtree.html#element-objects
方法释义:
--读取XML文件
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
--读取XML字符串
root = ET.fromstring(country_data_as_string)
--获取element object的四大属性tag、text、attrib以及tail
root.tag #root element的tag
root.text #root element的text
root.attrib #root element本身的attrib,dict格式的
root.tail #root element的tag结束到下一个tag之间的text
--通过DICT逻辑获取树形结构的text,表示第一个child的第二个child element的text
root[0][1].text
element object的方法:
Element.iter(tag) --遍历当前element树所有子节点的element(无论是子节点还是子节点的子节点),找到符合指定tag名的所有element,如果tag为空则遍历当前element树,返回所有节点element(包含当前父节点)。2.7和3.2之前的版本无此方法,可以用getiterator()代替。
Element.findall(tag) --遍历当前节点的直接子节点,找到符合指定tag名的element,返回由element组成的list
Element.find(tag) --遍历当前节点的直接子节点,找到符合指定tag名的第一个element
Element.get(key) --在当前element中获取符合指定attrib名的value
...其他方法参考官网
修改XML内容:
ElementTree.write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml") --将之前的修改写入XML
Element.set(key,value) --设置element attrib
Element.append(subelement) --新增一个子element,extends(subelements)是3.2的新增用法,输入参数必须是一个element序列
Element.remove(subelement) --删除指定tag的element
示例:
>>> for rank in root.iter('rank'):
... new_rank = int(rank.text) + 1
... rank.text = str(new_rank)
... rank.set('updated', 'yes')
...
>>> tree.write('output.xml')
处理含有Namespaces的XML文件:
--有一个如下的XML字符串:
<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"
xmlns="http://people.example.com">
<actor>
<name>John Cleese</name>
<fictional:character>Lancelot</fictional:character>
<fictional:character>Archie Leach</fictional:character>
</actor>
<actor>
<name>Eric Idle</name>
<fictional:character>Sir Robin</fictional:character>
<fictional:character>Gunther</fictional:character>
<fictional:character>Commander Clement</fictional:character>
</actor>
</actors>
方法一:在匹配时直接手动加上{uri}前缀
root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):
name = actor.find('{http://people.example.com}name')
print name.text
for char in actor.findall('{http://characters.example.com}character'):
print ' |-->', char.text
方法二:创建自己的namespace别名(其实只是在ns uri很长时可以少写点,实质并没有效率提升)
ns = {'real_person': 'http://people.example.com','role': 'http://characters.example.com'}
for actor in root.findall('real_person:actor', ns):
name = actor.find('real_person:name', ns)
print name.text
for char in actor.findall('role:character', ns):
print ' |-->', char.text
--两种方式的输出结果都是:
John Cleese
|--> Lancelot
|--> Archie Leach
Eric Idle
|--> Sir Robin
|--> Gunther
|--> Commander Clement
一个比较proxool.xml文件的示例代码:
# -*- coding:utf-8 -*-
# 用于进行配置文件的差异比较,2.7和3.2之前element没有iter()的遍历方法可以用getiterator()代替
import sys
from xml.etree import ElementTree as ET
from xml.dom import minidom
# 定义新旧XML文件分别为输入参数1和2
old_file = sys.argv[1]
new_file = sys.argv[2]
# 定义将新增tag加入旧XML文件的方法
def modify_xml(old_file,new_file):
if not new_file:
sys.exit(0)
tree_old = ET.parse(old_file) # 解析出整个ElementTree
tree_new = ET.parse(new_file)
global root # 定义全局变量root,只解析一次方便prettify_xml方法调用
root = tree_old.getroot()
root_old = tree_old.getroot().find("proxool") # 定位旧XML父节点proxool
root_new = tree_new.getroot().find("proxool")
old_dict = {} # 定义旧XML文件的tag/text字典
new_dict = {}
for e in root_old.getiterator(): # 遍历proxool树的所有节点element,包含其作为父节点的自身
# text为空时不能使用replace方法,因此加上判断;if e.text不能排除空字符' ',只能过滤none和''因此加上strip()过滤
if e.text and e.tag != 'proxool' and e.text.strip() != '':
old_dict[e.tag] = e.text.replace("\n", "").replace("\t", "")
for e in root_new.getiterator():
if e.text and e.tag != 'proxool' and e.text.strip() != '':
new_dict[e.tag] = e.text.replace("\n", "").replace("\t", "")
# 至此新旧XML文件的tag/text已经作为字典的元素存在了old_dict和new_dict中,只要比较这两个字典就可以拿到新增tag
for tag,text in new_dict.items():
if not old_dict.get(tag): # 当旧XML中找不到对应的tag时,进行tag新增操作
new_tag = ET.Element(tag) # 构造一个element
new_tag.text = text # 设置此element的text
root_old.append(new_tag) #将此element加入root_old节点下作为其子节点
else:
pass # 只为美观,可以不写else
tree_old.write(old_file + "_fixed",encoding="UTF-8") # 最后将append的整个ElementTree写入旧XML_fixed文件中,这样注释会丢失
# 新写入的XML项不是那么美观,再美化一下(发现结果更难看了,有待优化)
def prettify_xml(filename):
strTree = ET.tostring(root) #使用全局变量root
new_strTree = minidom.parseString(strTree).toprettyxml()
with open(filename,'w') as output:
output.write(new_strTree)
# 执行函数
modify_xml(old_file,new_file)
prettify_xml(old_file + "_fixed")
# Ps:后来发现使用ElementTree解析的XML文件很难美化,且不能处理注释,所以转用minidom处理XML文件了,详见《Python XML解析之DOM》
Python XML解析之ElementTree的更多相关文章
- Python XML解析(转载)
Python XML解析 什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是 ...
- python大法好——Python XML解析
Python XML解析 什么是XML? XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识. 它也是元标记语言,即定义了用于定义其他与 ...
- Python XML解析之DOM
DOM说明: DOM:Document Object Model API DOM是一种跨语言的XML解析机制,DOM把整个XML文件或字符串在内存中解析为树型结构方便访问. https://docs. ...
- Python XML解析
什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这 ...
- Python XML 解析
什么是 XML? XML 指可扩展标记语言(eXtensible Markup Language). XML 被设计用来传输和存储数据. XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并 ...
- Python XML 解析Ⅱ
make_parser方法 以下方法创建一个新的解析器对象并返回. 参数说明: parser_list - 可选参数,解析器列表 parser方法 以下方法创建一个 SAX 解析器并解析xml文档: ...
- Python xml 解析百度糯米信息
先利用爬虫利用百度糯米提供的api来采集北京当天的团购信息,保存为numi.html import xml.etree.ElementTree as ET import os class Nuomi( ...
- Python XML解析和处理
movies.xml <collection shelf = "New Arrivals"> <movie title = "Enemy Behind& ...
- 面试官问我:如何在 Python 中解析和修改 XML
摘要:我们经常需要解析用不同语言编写的数据.Python提供了许多库来解析或拆分用其他语言编写的数据.在此 Python XML 解析器教程中,您将学习如何使用 Python 解析 XML. 本文分享 ...
随机推荐
- RabbitMQ面试题
1.为什么要引入MQ系统,直接读写数据库不行吗?其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场景里用消息队列是什么? 面试官问你这个问题,期望的一个回答是说,你们公 ...
- bilibili源码泄漏后,程序员们从代码里扒出来的彩蛋
昨天bilibili又上热搜了,被某人在github上开了个账号,传了份整个后端代码到github,这是被人扒光了衣服看个精光啊. 这件事情,作为程序员的我们除了调侃和fork的同时,想一想,造成这个 ...
- 了解 HTTPS,读这篇文章就够了
今天接到个活儿,让我科普 HTTPS .讲 HTTP 我都“方”,想要通俗易懂的说完 HTTPS, 我有点“圆”.在讲什么是 HTTPS 之前,我们先来看个漫画. △ 图片来源于阮一峰的网络日志 ...
- 死磕 java集合之ArrayList源码分析
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 ArrayList是一种以数组实现的List,与数组相比,它具有动态扩展的能力,因此也可 ...
- 说一说MVC的CSRF(三)
用途:防止CSRF(跨网站请求伪造). 用法:在View->Form表单中:<%:Html.AntiForgeryToken()%> 在Controller->Action动作 ...
- 『扩展欧几里得算法 Extended Euclid』
Euclid算法(gcd) 在学习扩展欧几里得算法之前,当然要复习一下欧几里得算法啦. 众所周知,欧几里得算法又称gcd算法,辗转相除法,可以在\(O(log_2b)\)时间内求解\((a,b)\)( ...
- Python爬虫入门教程 21-100 网易云课堂课程数据抓取
写在前面 今天咱们抓取一下网易云课堂的课程数据,这个网站的数据量并不是很大,我们只需要使用requests就可以快速的抓取到这部分数据了. 你第一步要做的是打开全部课程的地址,找出爬虫规律, 地址如下 ...
- 前端笔记之HTML5&CSS3(上)新特性&音频视频&本地存储&自定义属性
一.HTML5简介 HTML 5 的第一份正式草案已于2008年1月22日公布.HTML5 仍处于完善之中.然而,大部分现代浏览器已经具备了某些 HTML5 支持. 2014年10月29日,万维网联盟 ...
- Java开发知识之Java的包装类
Java开发知识之Java的包装类 一丶什么是包装类 包装类的意思就是对基本数据类型封装成一个类.这些类都是Number的子类.区别就是封装数据类型不同.包含的方法基本相同. 具体可以查询JAVA A ...
- RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)
在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ...