XML是一种你可能经常听说,但未必深入了解的技术。它的全称是“可扩展标记语言”。简单来说,它是一种用来存储和传输数据的格式,其核心在于通过标签来给数据赋予清晰的结构和含义。
你可以把XML想象成一种没有预定义标签的html。在HTML里,<p>代表段落,<a>代表链接,这些都是固定好的。但在XML里,你可以创建任何你需要的标签,比如 <书名>、<价格> 或 <库存数量>。这种灵活性使得它成为在不同系统之间交换数据的理想选择,尤其是在Web服务和配置文件等领域应用广泛。
一个典型的XML文件看起来是这样的,它结构清晰,既能被机器高效读取,也方便人类理解:
<书店>
<图书 类别="编程">
<书名>Python编程从入门到实践</书名>
<作者>约翰·史密斯</作者>
<价格>89.00</价格>
</图书>
<图书 类别="数据科学">
<书名>利用Python进行数据分析</书名>
<作者>简·多伊</作者>
<价格>99.00</价格>
</图书>
</书店>当我们需要在Python程序中读取或修改XML数据时,就需要用到解析器。Python提供了三种主要方法,它们各有特点,适用于不同的场景。
ElementTree:这是最常用、最被推荐给初学者的方法。它在Python标准库中,api简单直观,在性能和功能之间取得了很好的平衡。
SAX:这是一种基于事件驱动的解析方式。解析器会顺序读取XML文件,在遇到开始标签、结束标签或文本内容时触发相应的事件。它不需要将整个文件加载到内存中,因此非常适合处理非常大的XML文件。
dom:这种方式会将整个XML文档一次性读入内存,并构建成一个树形结构。你可以随意地在树中进行导航、修改或删除节点。它的优点是功能全面,但缺点是内存开销大,不适合处理大文件。
下面,我们通过fly63教程上的实例,来详细了解一下这三种方法的具体用法。
xml.etree.ElementTree模块是处理XML任务的首选。它的概念很简单:整个XML文档是一棵“树”,每个标签是一个“元素”节点。
如何读取和解析XML?
XML数据可以来自字符串,也可以来自文件。
import xml.etree.ElementTree as ET
# 如果XML是一个字符串
xml_data = '<root><book>Python Basics</book></root>'
root_element = ET.fromstring(xml_data)
# 如果XML是一个文件
tree = ET.parse('books.xml')
root_element = tree.getroot()如何遍历和提取数据?
获取根元素后,我们可以通过循环和查找来获取我们需要的信息。
import xml.etree.ElementTree as ET
# 假设这是我们解析得到的根元素
xml_string = '''
<书店>
<图书>
<书名>Python编程从入门到实践</书名>
<作者>约翰·史密斯</作者>
<价格>89.00</价格>
</图书>
<图书>
<书名>利用Python进行数据分析</书名>
<作者>简·多伊</作者>
<价格>99.00</价格>
</图书>
</书店>
'''
root = ET.fromstring(xml_string)
# 查找所有名为“图书”的元素
for book in root.findall('图书'):
# 在每个“图书”元素下,查找“书名”、“作者”子元素,并获取其文本内容
title = book.find('书名').text
author = book.find('作者').text
price = book.find('价格').text
print(f'书名:{title}, 作者:{author}, 价格:{price}')运行上面的代码,输出结果是:
书名:Python编程从入门到实践, 作者:约翰·史密斯, 价格:89.00
书名:利用Python进行数据分析, 作者:简·多伊, 价格:99.00如何创建和修改XML?
ElementTree同样能让我们从零开始创建XML文档,或者修改已有的文档。
import xml.etree.ElementTree as ET
# 创建根元素
root = ET.Element('书店')
# 创建第一本图书及其子元素
book1 = ET.SubElement(root, '图书')
title1 = ET.SubElement(book1, '书名')
title1.text = 'Python编程从入门到实践'
author1 = ET.SubElement(book1, '作者')
author1.text = '约翰·史密斯'
# 将树形结构写入文件
tree = ET.ElementTree(root)
tree.write('新书籍.xml', encoding='utf-8', xml_declaration=True)这段代码会生成一个名为“新书籍.xml”的文件,其内容就是我们定义的XML结构。
SAX的工作方式与ElementTree完全不同。它不像后者那样在内存中构建整个树的模型,而是一边读取文件,一边告诉你它读到了什么(比如“遇到了一个开始标签”、“遇到了一段文本”)。你需要提前编写好事件处理函数,告诉程序当这些事件发生时该做什么。
这种方法听起来复杂,但它的最大优点是占用内存极少,因为它从不把整个文档载入内存。这对于处理几个GB大小的XML文件来说是唯一可行的方案。
下面是一个使用SAX解析电影XML文件的例子:
import xml.sax
# 定义一个事件处理器类
class MovieHandler(xml.sax.ContentHandler):
def __init__(self):
self.current_data = ""
self.title = ""
self.type = ""
self.format = ""
# 遇到开始标签时调用
def startElement(self, tag_name, attributes):
self.current_data = tag_name
if tag_name == "movie":
print("*****电影*****")
# 获取标签的属性
movie_title = attributes["title"]
print(f"标题: {movie_title}")
# 遇到文本内容时调用
def characters(self, content):
if self.current_data == "type":
self.type = content
elif self.current_data == "format":
self.format = content
# 遇到结束标签时调用
def endElement(self, tag_name):
if self.current_data == "type":
print(f"类型: {self.type}")
elif self.current_data == "format":
print(f"格式: {self.format}")
self.current_data = ""
# 主程序
parser = xml.sax.make_parser()
# 关闭命名空间解析(通常是为了简化处理)
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
# 设置我们自定义的事件处理器
handler = MovieHandler()
parser.setContentHandler(handler)
# 开始解析文件
parser.parse("movies.xml")DOM解析方式将XML文档整个加载到内存中,形成一个“文档树”。你可以像操作对象一样,随意访问和操作树上的任何一个节点。
from xml.dom import minidom
# 解析XML文件
DOMTree = minidom.parse("movies.xml")
collection = DOMTree.documentElement
# 获取并打印根元素的属性
if collection.hasAttribute("shelf"):
print(f"根元素类别: {collection.getAttribute('shelf')}")
# 获取所有名为“movie”的元素
movies = collection.getElementsByTagName("movie")
# 遍历每个电影元素
for movie in movies:
print("*****电影*****")
# 获取属性
if movie.hasAttribute("title"):
print(f"标题: {movie.getAttribute('title')}")
# 获取子元素的文本内容
# getElementsByTagName会返回一个列表,我们取第一个
movie_type = movie.getElementsByTagName('type')[0]
movie_format = movie.getElementsByTagName('format')[0]
print(f"类型: {movie_type.firstChild.data}")
print(f"格式: {movie_format.firstChild.data}")DOM的优点是编程模型直观,可以随机访问任何节点。缺点是当XML文件非常大时,会消耗大量内存,可能导致程序变慢。
大多数情况下,请选择ElementTree。它简单、快速,功能对于日常任务来说已经足够。
当你需要处理非常大的XML文件,而电脑内存有限时,应该选择SAX。
当你需要频繁地、随机地修改XML文档结构,或者不介意内存占用时,可以考虑使用DOM。
希望这份来自fly63教程的指南能帮助你理解XML以及如何在Python中有效地处理它。掌握这三种解析方法,将使你能够从容应对各种与XML数据处理相关的编程任务。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!