Python3入门指南Python语言的特点和实际应用Python3环境搭建配置VSCode进行Python开发Python基础语法Python变量与数据类型Python数据类型转换Python解释器使用Python注释使用Python运算符Python数字类型Python字符串操作Python列表操作Python元组使用Python字典使用Python集合使用Python条件控制详解Python循环语句详解Python编程入门实践Python推导式详解Python迭代器和生成器Python with语句详解Python函数详解Python lambda(匿名函数)Python装饰器Python数据结构Python模块和包使用Python中__name__和__main__的用法Python输入输出:从基础到文件操作Python文件操作Python OS模块使用Python错误和异常处理Python面向对象编程Python命名空间和作用域Python虚拟环境:venv详细教程Python类型注解Python标准库常用模块Python正则表达式Python CGI编程Python MySQL(mysql-connector驱动)Python MySQL(PyMySQL驱动)Python网络编程Python发送邮件Python多线程编程Python XML解析Python JSON解析Python日期和时间处理Python操作MongoDBPython urllib库使用Python uWSGI 安装与配置Python pip包管理工具Python operator模块Python math模块Python requests模块HTTP请求Python random模块Python OpenAI库Python AI绘画制作Python statistics模块Python hashlib模块:哈希加密Python量化交易Python pyecharts数据可视化Python Selenium网页自动化Python BeautifulSoup网页数据提取Python Scrapy爬虫框架Python Markdown转HTMLPython sys模块Python Pickle模块:数据存储Python subprocess模块Python queue队列模块Python StringIO内存文件操作Python logging日志记录Python datetime日期时间处理Python re正则表达式Python csv表格数据处理Python threading 多线程编程Python asyncio 异步编程Python PyQt 图形界面开发Python 应用方向和常用库框架

Python XML解析

XML是一种你可能经常听说,但未必深入了解的技术。它的全称是“可扩展标记语言”。简单来说,它是一种用来存储和传输数据的格式,其核心在于通过标签来给数据赋予清晰的结构和含义。

你可以把XML想象成一种没有预定义标签的html。在HTML里,<p>代表段落,<a>代表链接,这些都是固定好的。但在XML里,你可以创建任何你需要的标签,比如 <书名>、<价格> 或 <库存数量>。这种灵活性使得它成为在不同系统之间交换数据的理想选择,尤其是在Web服务和配置文件等领域应用广泛。

一个典型的XML文件看起来是这样的,它结构清晰,既能被机器高效读取,也方便人类理解:

<书店>
    <图书 类别="编程">
        <书名>Python编程从入门到实践</书名>
        <作者>约翰·史密斯</作者>
        <价格>89.00</价格>
    </图书>
    <图书 类别="数据科学">
        <书名>利用Python进行数据分析</书名>
        <作者>简·多伊</作者>
        <价格>99.00</价格>
    </图书>
</书店>

Python解析XML的三种主流方法

当我们需要在Python程序中读取或修改XML数据时,就需要用到解析器。Python提供了三种主要方法,它们各有特点,适用于不同的场景。

  1. ElementTree:这是最常用、最被推荐给初学者的方法。它在Python标准库中,api简单直观,在性能和功能之间取得了很好的平衡。

  2. SAX:这是一种基于事件驱动的解析方式。解析器会顺序读取XML文件,在遇到开始标签、结束标签或文本内容时触发相应的事件。它不需要将整个文件加载到内存中,因此非常适合处理非常大的XML文件。

  3. dom:这种方式会将整个XML文档一次性读入内存,并构建成一个树形结构。你可以随意地在树中进行导航、修改或删除节点。它的优点是功能全面,但缺点是内存开销大,不适合处理大文件。

下面,我们通过fly63教程上的实例,来详细了解一下这三种方法的具体用法。


使用ElementTree解析XML

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解析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

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数据处理相关的编程任务。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/course/36_2116

目录选择