参考网址:
菜鸟教程提供了基本的XML编程接口DOM、SAX,以及轻量级ElementTree的简易概念说明和一些示例。DOM是一种跨语言的XML解析机制,通过将整个XML在内存中解析为一个树来操作,ElementTree未做太多介绍,你可以到官网网址查看其详细的方法释义。
ElementTree是Python中最快捷的XML解析方式,可以看做一个轻量级的DOM,本文主要讲ElementTree,ElementTree在解析XML时非常方便,DOM比较笨重但是功能齐全,例如ElementTree处理XML注释时就很不方便(详见https://bugs.python.org/issue8277),此时用DOM比较好。

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数据:

--读取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>
其中包含fictional和default两个命名空间,这意味fictional:xxx格式的tags、attributes都会被自动扩展为{uri}xxx格式。而如果还定义了默认命名空间xmlns,那么所有无前缀的tags也会被扩展为{url}xxx格式。
有两种将此类XML处理为普通格式的方法:

方法一:在匹配时直接手动加上{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的更多相关文章

  1. Python XML解析(转载)

    Python XML解析 什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是 ...

  2. python大法好——Python XML解析

    Python XML解析 什么是XML? XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识. 它也是元标记语言,即定义了用于定义其他与 ...

  3. Python XML解析之DOM

    DOM说明: DOM:Document Object Model API DOM是一种跨语言的XML解析机制,DOM把整个XML文件或字符串在内存中解析为树型结构方便访问. https://docs. ...

  4. Python XML解析

    什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这 ...

  5. Python XML 解析

    什么是 XML? XML 指可扩展标记语言(eXtensible Markup Language). XML 被设计用来传输和存储数据. XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并 ...

  6. Python XML 解析Ⅱ

    make_parser方法 以下方法创建一个新的解析器对象并返回. 参数说明: parser_list - 可选参数,解析器列表 parser方法 以下方法创建一个 SAX 解析器并解析xml文档: ...

  7. Python xml 解析百度糯米信息

    先利用爬虫利用百度糯米提供的api来采集北京当天的团购信息,保存为numi.html import xml.etree.ElementTree as ET import os class Nuomi( ...

  8. Python XML解析和处理

    movies.xml <collection shelf = "New Arrivals"> <movie title = "Enemy Behind& ...

  9. 面试官问我:如何在 Python 中解析和修改 XML

    摘要:我们经常需要解析用不同语言编写的数据.Python提供了许多库来解析或拆分用其他语言编写的数据.在此 Python XML 解析器教程中,您将学习如何使用 Python 解析 XML. 本文分享 ...

随机推荐

  1. 【Spark篇】---Spark解决数据倾斜问题

    一.前述 数据倾斜问题是大数据中的头号问题,所以解决数据清洗尤为重要,本文只针对几个常见的应用场景做些分析 . 二.具体方法  1.使用Hive ETL预处理数据 方案适用场景: 如果导致数据倾斜的是 ...

  2. BBS论坛(十二)

    12.1.图形验证码生成 (1)utils/captcha/init.py import random import string # Image:一个画布 # ImageDraw:一个画笔 # Im ...

  3. CORS(跨域)请求总结和测试

    一.简单请求与非简单请求 跨域请求分为简单与非简单请求,同时满足以下两种条件的可以确定为简单请求. 简单请求的请求方法 请求方法 说明 head 发送头部信息 get   post   简单请求的HT ...

  4. Redis学习——数据结构介绍(四)

    一.简介 作为一款key-value 的NoSQL数据库,Redis支持的数据结构比较丰富,有:String(字符串) .List(列表) .Set(集合) .Hash(哈希) .Zset(有序集合) ...

  5. Spring Security OAuth 2.0

    续·前一篇<OAuth 2.0> OAuth 2.0 Provider 实现 在OAuth 2.0中,provider角色事实上是把授权服务和资源服务分开,有时候它们也可能在同一个应用中, ...

  6. Kafka~HelloWorld得来不易

    今天连搭了zookeeper和kafka的环境,并部署成功,但在.net驱动的操作下,没有消费成功,原因何在? 防火墙 zookeeper没运行? kafka没有公开IP? 第一感觉也就是这向个原因了 ...

  7. 基于spark实现并行化Apriori算法

    详细代码我已上传到github:click me 一. 实验要求         在 Spark2.3 平台上实现 Apriori 频繁项集挖掘的并行化算法.要求程序利用 Spark 进行并行计算. ...

  8. 使用RESTful风格开发Java Web

    什么是RESTful风格? REST是REpresentational State Transfer的缩写(一般中文翻译为表述性状态转移),REST 是一种体系结构,而 HTTP 是一种包含了 RES ...

  9. RabbitMQ消息队列(十二)-性能测试

    硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5.5的虚拟化平台,在子系统中安装RabbitMQ和 ...

  10. Java开发知识之JAVA的反射

    目录 Java中的反射机制 一丶什么是反射机制 二丶Class类,自描述类.获取类名的三种方法 1.使用静态属性Class获取 2.使用Class方法 forName()获取自描述Class 3.使用 ...