参考网址:
菜鸟教程提供了基本的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. Storm学习笔记 - 消息容错机制

    Storm学习笔记 - 消息容错机制 文章来自「随笔」 http://jsynk.cn/blog/articles/153.html 1. Storm消息容错机制概念 一个提供了可靠的处理机制的spo ...

  2. 想成为Python全栈开发工程师必须掌握的技能

    什么是Python全栈工程师? 即从前端页面的实现,到后台代码的编写,再到数据库的管理,一人可以搞定一个公司网站的所有事情,真正实现全栈开发. 全栈只是个概念 也分很多种类 真正的全栈工程师涵盖了we ...

  3. Linux 设置自启动服务

     0 为停机,机器关闭.(千万不要把initdefault设置为0 )    1 为单用户模式,就像Win9x下的安全模式类似.    2 为多用户模式,但是没有NFS支持.    3 为完整的多用户 ...

  4. C# 多线程学习笔记 - 1

    本文主要针对 GKarch 相关文章留作笔记,仅在原文基础上记录了自己的理解与摘抄部分片段. 遵循原作者的 CC 3.0 协议. 如果想要了解更加详细的文章信息内容,请访问下列地址进行学习. 原文章地 ...

  5. knockoutjs 上自己实现的flux

    在knockoutjs 上实现 Flux 单向数据流 状态机,主要解决多个组件之间对数据的耦合问题. 一.其实简单 flux的设计理念和实现方案,很大程度上人借鉴和参考了Vuex的实现,只是简化了某些 ...

  6. jni c++

        java与c/c++之间的数据交互     JNI     上述两篇文章对jni的讲解比较详细,各有利弊,就文章1来说,开门见山,直接阐述了java和C/C++的交互方式:文章2是一篇百度文库 ...

  7. Python爬虫入门教程 13-100 斗图啦表情包多线程爬取

    斗图啦表情包多线程爬取-写在前面 今天在CSDN博客,发现好多人写爬虫都在爬取一个叫做斗图啦的网站,里面很多表情包,然后瞅了瞅,各种实现方式都有,今天我给你实现一个多线程版本的.关键技术点 aioht ...

  8. MySQL系列--2.常用的命令

    1 .创建数据库 #语法: CREATE DATABASE dbName; #创建数据库rms create database rms; 2.切换数据库 #选择数据库 USE dbName; #选择数 ...

  9. 五一之起一台服务器玩玩-centosl系统搭建lamp

    昨天看到有的扫描软件会扫描公网主机开放的端口,我现在就用了ssh远程登录21和22端口那不是很容易被猜想到.so,我决定要改这个端口,同时这个改端口给我打开了防火墙和ip协议和网络安全的大门. 我之前 ...

  10. LeetCode专题-Python实现之第14题:Longest Common Prefix

    导航页-LeetCode专题-Python实现 相关代码已经上传到github:https://github.com/exploitht/leetcode-python 文中代码为了不动官网提供的初始 ...