概述
什么是XML?
XML 指可扩展标记语言(eXtensible Markup Language)。 XML 被设计用来传输和存储数据。
XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。
它也是元标记语言,即定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。
xml构成
XML由3个部分构成,它们分别是:
- 文档类型定义(Document Type Definition,DTD),即XML的布局语言
- 可扩展的样式语言(Extensible Style Language,XSL),即XML的样式表语言
- 可扩展链接语言(Extensible Link Language,XLL)
Python解析xml的方法
常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,当然使用场合也不同。
python有三种方法解析XML,SAX,DOM,以及ElementTree:
- SAX (simple API for XML )
python 标准库包含SAX解析器,SAX用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。 - DOM(Document Object Model)
将XML数据在内存中解析成一个树,通过对树的操作来操作XML。 - ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
本文只介绍ElementTree方式解析xml。
一个基本xml片段
下面我们尝试解析下面这一段xml:
<?xml version="1.0"?><data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country></data>
或是将上面这段xml内容保存至xml_data.xml中。
代码示例
下面通过一段完整的代码演示如何读取、修改和保存xml。
#-*- coding:utf-8 -*-__author__ = "苦叶子"# 导入ElementTreeimport xml.etree.ElementTree as ETif __name__ == "__main__":
print("python xml解析实例")
data = """<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
"""
# 载入xml的两种方式,一种从文件,一种从xml字符串
# 注意区别:从xml字符串加载的xml直接返回root元素对象
# 而从文件加载xml返回是xml树
# 大家根据实际情况来决定用哪种方式即可
# 本示例从xml字符串载入进行演示
# 从文件加载xml,获取xml tree节点
# tree = ET.parse('xml_data.xml')
# 获取根节点
# root = tree.getroot()
# 从字符串加载xml
root = ET.fromstring(data) # 打印下根节点的节点tag, 输出data
print(root.tag) # 遍历下根节点的所有子节点及其属性
print("---" * 10) for child in root:
print(child.tag, " ", child.attrib)
# 找所有的year节点玩下
print("---" * 10) for child in root.iter("year"): # 打印出year节点的tag和text
print(child.tag, " ", child.text)
# 修改下节点的text试试, 把year节点所有2011修改为2017
print("---" * 10) for child in root.iter("year"): if child.text == "2011":
child.text = "2017"
child.set('updated', 'yes')
# 打印下修改后的xml所有的year节点
print("将2011 -> 2017") for child in root.iter("year"): # 打印出year节点的tag和text
print(child.tag, " ", child.text)
# 给每个country节点新增一个<wx>开源优测</wx>的节点试试
print("---" * 10) for child in root.iter("country"):
wx = ET.SubElement(child, "wx")
wx.text = "开源优测"
# 遍历wx节点,并打印
for child in root.iter("wx"):
print(child.tag, " ", child.text)
# 下面演示删除所有的neighbor节点
# 当然你自己可以加判断条件删除指定的节点,自行尝试吧
print("---" * 10) for child in root.findall("neighbor"):
root.remove(child)
# 保存上述操作后的xml至xml_write_data.xml
xml_update_data = ET.tostring(root, encoding="unicode") # 写入xml_write_data.xml
import codecs
fp = codecs.open("xml_write_data.xml","w","utf-8")
fp.write(xml_update_data)
fp.close()
经过上述一系列代码操作后保存至xml_write_data.xml中的xml内容如下:
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
<wx>开源优测</wx></country>
<country name="Singapore">
<rank>4</rank>
<year updated="yes">2017</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
<wx>开源优测</wx></country>
<country name="Panama">
<rank>68</rank>
<year updated="yes">2017</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
<wx>开源优测</wx></country></data>
小结
本文所述仅仅是ElementTree的极小部分功能,更多的功能请参见官方文档学习。