参考网址:
菜鸟教程提供了基本的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. 执行find / -name *.sh时报错 find: 路径必须在表达式之前: start-ressvr-release.sh

    想查找一个包含4000多文件的目录下所有.sh结尾的文件 使用命令     find  ./ -name *.sh     (本身已经在要查找的目录里了) 结果报错:  解决方法一:find ./ - ...

  2. HoloLens开发手记- SpectatorView for iOS编译指南

    微软前两天发布了HoloLens 2,给MR开发带来了新的希望,全面的性能和显示效果提升,让人期待. 去年推出的预览版的全新SpectatorView for iOS解决方案,这允许我们直接使用带AR ...

  3. mybatis 批量更新 Parameter '__frch_item_0' not found. Available parameters are [list]

    一次在做批量更新数据的时候报错 Parameter '__frch_item_0' not found. Available parameters are [list] 记过反复查找,最后才发现是一个 ...

  4. Python 字典和集合基于哈希表实现

    哈希表作为基础数据结构我不多说,有兴趣的可以百度,或者等我出一篇博客来细谈哈希表.我这里就简单讲讲:哈希表不过就是一个定长数组,元素找位置,遇到哈希冲突则利用 hash 算法解决找另一个位置,如果数组 ...

  5. AspNetCore 基于流下载文件与示例代码

    昨天说了,AspNetCore如何进行上传文件,其中写了两种方式ajax与模型,其文章地址为:https://www.cnblogs.com/ZaraNet/p/9949167.html 那么既然有上 ...

  6. 使用 Nginx 在 Linux 上托管 ASP.NET Core 应用程序

    本文于2019年04月10日将标题「CentOS7 部署 ASP.NET Core应用程序」修改为「使用 Nginx 在 Linux 上托管 ASP.NET Core 应用程序」. 环境准备 VMwa ...

  7. Mongo 用户管理

    开启用户管理 auth = true 在配置文件或者参数中设置为改选项 开启认证服务,注意一点,很多人说在没有设置用户和配置用户之前,应该先不要开启,等设置完用户后再开启该参数,目前在win2008 ...

  8. Jvm垃圾回收器(算法篇)

    在<Jvm垃圾回收器(基础篇)>中我们主要学习了判断对象是否存活还是死亡?两种基础的垃圾回收算法:引用计数法.可达性分析算法.以及Java引用的4种分类:强引用.软引用.弱引用.虚引用.和 ...

  9. 用meterpreter实现跳板机

      meterpreter跳板机 背景:渗透测试者A拿到了B主机的控制权,但没有拿到ssh密码(不能打ssh隧道).现需横向移动渗透内网主机C,为了避免动作过大不便直接在B上对C进行渗透,其中C不能出 ...

  10. webpack4.0各个击破(1)—— html部分

    webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...