0

0

python中怎么解析XML文件?

穿越時空

穿越時空

发布时间:2025-09-14 22:16:01

|

1043人浏览过

|

来源于php中文网

原创

使用ElementTree解析XML时,核心技巧包括:利用ET.parse()或ET.fromstring()加载数据,通过getroot()获取根元素,遍历子元素并访问tag、attrib和text属性;使用find、findall和iter方法进行元素查找,结合命名空间字典处理带命名空间的标签,推荐用get()安全获取属性值。

python中怎么解析xml文件?

在Python里解析XML文件,最常用的方法是使用内置的

xml.etree.ElementTree
模块,它提供了一种轻量级且高效的方式来处理XML数据。对于更复杂或者对性能有更高要求的场景,
lxml
库则是一个功能更强大、速度更快的选择。说白了,看你需求,一般情况
ElementTree
就够用了。

解决方案

要解析XML文件,我们通常会加载整个XML文档到内存中,然后像遍历树一样去访问其中的元素、属性和文本内容。

首先,你需要导入

ElementTree
模块,通常我们会给它一个别名
ET
,这样用起来更简洁。

import xml.etree.ElementTree as ET

从文件解析: 如果你有一个XML文件(比如

data.xml
),你可以这样加载它:

# data.xml 内容示例:
# <root>
#     <item id="1">
#         <name>苹果</name>
#         <price currency="USD">1.99</price>
#     </item>
#     <item id="2">
#         <name>香蕉</name>
#         <price currency="USD">0.79</price>
#     </item>
# </root>

try:
    tree = ET.parse('data.xml')
    root = tree.getroot() # 获取根元素
except FileNotFoundError:
    print("错误:data.xml 文件未找到。")
except ET.ParseError as e:
    print(f"错误:解析XML文件时出错 - {e}")

字符串解析 如果你的XML数据是一个字符串,你可以用

ET.fromstring()
方法:

xml_string = """
<root>
    <item id="3">
        <name>橙子</name>
        <price currency="EUR">1.20</price>
    </item>
</root>
"""
root = ET.fromstring(xml_string)

获取到

root
元素后,就可以开始遍历和提取数据了:

立即学习Python免费学习笔记(深入)”;

print(f"根元素标签: {root.tag}")

# 遍历所有子元素
for child in root:
    print(f"子元素标签: {child.tag}, 属性: {child.attrib}") # attrib 返回一个字典

    # 获取特定子元素的文本内容
    name_element = child.find('name')
    if name_element is not None:
        print(f"  商品名称: {name_element.text}")

    price_element = child.find('price')
    if price_element is not None:
        print(f"  价格: {price_element.text}, 货币: {price_element.attrib.get('currency')}")

# 直接查找所有符合条件的元素
all_items = root.findall('item')
print(f"\n找到了 {len(all_items)} 个商品。")

使用
ElementTree
解析XML文件的核心技巧有哪些?

在我的实践中,掌握

ElementTree
的核心技巧,主要是理解它如何将XML文档映射为Python对象,以及如何高效地进行导航和数据提取。最关键的几点是:

  1. ET.parse()
    ET.fromstring()
    这是入口点。
    parse
    用于文件,
    fromstring
    用于内存中的字符串。搞清楚你数据的来源,选对方法是第一步。
  2. getroot()
    拿到整个XML树的“根”,所有操作都从这里开始。就像你进入一栋房子,得先找到大门。
  3. 元素对象(Element Object): 这是
    ElementTree
    的核心。每个XML标签被解析后,都会变成一个
    Element
    对象。这个对象有几个重要的属性:
    • tag
      :元素的标签名,比如
      <name>
      tag
      就是
      'name'
    • attrib
      :一个字典,存储了元素的所有属性。比如
      <price currency="USD">
      attrib
      就是
      {'currency': 'USD'}
    • text
      :元素开始标签和结束标签之间的文本内容。例如
      <name>苹果</name>
      text
      就是
      '苹果'
      。如果元素内部还有子元素,
      text
      只会包含紧跟在开标签后的文本。
    • tail
      :元素结束标签后的文本内容。这个比较少用,但在处理混合内容(text-interspersed-with-tags)时会有用。
  4. 导航方法:
    • 直接迭代:
      for child in parent_element:
      这样可以遍历一个元素的所有直接子元素。这是最直观的。
    • find(tag)
      查找当前元素的第一个匹配
      tag
      的直接子元素。如果找到多个,它只返回第一个。
    • findall(tag)
      查找当前元素所有匹配
      tag
      的直接子元素,返回一个列表。这个方法非常常用,因为它能获取所有相同类型的子节点。
    • iter(tag=None)
      这是一个强大的遍历器,可以递归地遍历当前元素及其所有后代元素。如果你想找到XML文档中所有某个特定标签的元素,无论它在哪个层级,
      iter()
      就非常方便。例如
      root.iter('name')
      会找到所有名为
      name
      的元素。
    • XPath支持:
      ElementTree
      对XPath的支持比较基础,主要限于路径表达式。例如,
      root.findall('./item/name')
      可以找到所有
      item
      下的
      name
      元素。但对于更复杂的XPath查询(比如条件过滤、属性值匹配),它就显得力不从心了,这时候
      lxml
      的优势就体现出来了。

记住,

ElementTree
的设计哲学就是“简单够用”,所以它不会像
lxml
那样提供全套的XPath/XSLT支持,但在绝大多数场景下,这些基础方法已经足够我们高效地完成任务了。

处理大型XML文件时,
ElementTree
lxml
各有何优劣?

处理大型XML文件时,性能和内存占用就成了绕不开的话题。

ElementTree
lxml
在这方面各有特点,选择哪个取决于你的具体需求和文件大小。

xml.etree.ElementTree
的优劣:

  • 优点:
    • 内置: 无需安装任何第三方库,Python环境自带,开箱即用。这在部署环境受限或者希望减少依赖时是个大优势。
    • 简单易学: API设计相对简洁,对于熟悉Python的人来说上手很快。
    • 足够日常使用: 对于中小型的XML文件,或者XML结构比较规整、查询需求不复杂的场景,
      ElementTree
      的性能完全够用。
  • 缺点:
    • 内存占用:
      ElementTree
      默认是“DOM-like”解析器,它会一次性将整个XML文档加载到内存中,构建成一个完整的树形结构。对于几百MB甚至GB级别的超大型XML文件,这会导致巨大的内存消耗,可能直接让你的程序崩溃。
    • 性能: 相较于
      lxml
      ElementTree
      在解析速度上通常会慢一些,尤其是在处理大量数据时。
    • XPath支持有限: 它的XPath支持比较基础,很多高级的XPath功能(如函数、轴、复杂谓词)都无法使用,这在需要复杂查询时会非常不便。
    • 缺乏SAX-like解析:
      ElementTree
      本身不提供事件驱动(SAX-like)的增量解析方式,无法在读取XML的同时处理数据,这进一步限制了它处理大文件的能力。

lxml
的优劣:

  • 优点:
    • 性能卓越:
      lxml
      底层使用了C语言实现的
      libxml2
      libxslt
      库,这使得它在解析速度和内存效率上都远超
      ElementTree
      。对于大型XML文件,它的解析速度可以快好几倍。
    • 强大的XPath/XSLT支持:
      lxml
      提供了几乎完整的XPath 1.0/2.0支持,以及XSLT转换功能。这意味着你可以用非常强大和灵活的查询语言来定位和提取XML数据,极大地简化了复杂的数据处理逻辑。
    • 增量解析(
      iterparse
      ):
      lxml
      提供了
      iterparse
      功能,这是一种事件驱动(SAX-like)的解析方式。它允许你在解析XML文档的同时处理元素,而无需将整个文档加载到内存。这对于处理超大型XML文件(例如几GB的文件)至关重要,因为它能显著降低内存占用。
    • HTML解析:
      lxml
      也能高效解析HTML文档,并提供类似XML的API进行操作,这在网络爬虫等场景下非常有用。
  • 缺点:
    • 外部依赖: 需要通过
      pip install lxml
      安装,并且依赖底层的C库。在某些特定环境(如没有编译工具链的轻量级容器)中安装可能会遇到一些麻烦。
    • API略复杂: 相对于
      ElementTree
      lxml
      的API更丰富,功能也更多,这可能意味着学习曲线稍陡峭一些,尤其是在使用高级功能时。

总结:

Imagine By Magic Studio
Imagine By Magic Studio

AI图片生成器,用文字制作图片

下载

我的经验是,如果你的XML文件不大(比如几十MB以内),并且查询需求不复杂,

ElementTree
是首选,因为它简单、无依赖。但一旦你开始遇到内存溢出、解析速度慢或者需要复杂XPath查询时,毫不犹豫地切换到
lxml
。它在处理大型、复杂XML文档方面,几乎是Python生态系统中的不二之选。

如何在解析XML时处理命名空间(Namespaces)和属性(Attributes)?

处理XML的命名空间和属性是日常工作中经常遇到的情况,尤其是在集成不同系统或者处理标准XML格式(如SOAP、RSS、Atom)时。

处理属性(Attributes):

属性相对直观,每个

Element
对象都有一个
attrib
属性,它是一个字典,键是属性名,值是属性值。

import xml.etree.ElementTree as ET

xml_data = """
<root>
    <user id="123" status="active">
        <name lang="en">John Doe</name>
        <email>john.doe@example.com</email>
    </user>
    <user id="456" status="inactive">
        <name lang="zh">张三</name>
    </user>
</root>
"""

root = ET.fromstring(xml_data)

for user in root.findall('user'):
    user_id = user.get('id') # 使用get()方法获取属性,更安全,如果属性不存在返回None
    user_status = user.attrib.get('status', 'unknown') # 也可以使用字典的get方法,并提供默认值

    print(f"User ID: {user_id}, Status: {user_status}")

    name_element = user.find('name')
    if name_element is not None:
        name_text = name_element.text
        name_lang = name_element.get('lang') # 获取name元素的lang属性
        print(f"  Name: {name_text}, Language: {name_lang}")

这里我更推荐使用

element.get('attribute_name')
来获取属性,因为它在属性不存在时会返回
None
,避免了直接访问
element.attrib['attribute_name']
可能导致的
KeyError

处理命名空间(Namespaces):

命名空间是XML中一个稍微复杂但非常重要的概念,它用来避免元素和属性名称冲突。当XML文档中包含命名空间时,解析起来就需要一些特别的处理。

ElementTree
在内部会将带命名空间的标签名表示为
{namespace_uri}local_name
的形式。例如,如果XML中有
<ns:item xmlns:ns="http://example.com/ns">
,那么
item
标签的内部表示就是
{http://example.com/ns}item

import xml.etree.ElementTree as ET

xml_with_ns = """
<data xmlns="http://default.com/ns" xmlns:prod="http://products.com/ns">
    <prod:item prod:id="A101">
        <prod:name>Laptop</prod:name>
        <price>1200</price>
    </prod:item>
    <prod:item prod:id="A102">
        <prod:name>Mouse</prod:name>
        <price>25</price>
    </prod:item>
    <info>Some general information</info>
</data>
"""

root = ET.fromstring(xml_with_ns)

# 1. 明确知道命名空间URI时:
# 注意:默认命名空间也会被ElementTree以URI形式处理
print("--- 明确知道命名空间URI ---")
default_ns_tag = "{http://default.com/ns}info"
info_element = root.find(default_ns_tag)
if info_element is not None:
    print(f"Info (default NS): {info_element.text}")

# 对于带前缀的命名空间,同样需要使用完整的URI
prod_item_tag = "{http://products.com/ns}item"
for item in root.findall(prod_item_tag):
    prod_id = item.get('{http://products.com/ns}id') # 属性的命名空间也要完整表示
    prod_name_element = item.find('{http://products.com/ns}name')
    price_element = item.find('{http://default.com/ns}price') # 注意这里price在默认命名空间下

    name_text = prod_name_element.text if prod_name_element is not None else "N/A"
    price_text = price_element.text if price_element is not None else "N/A"
    print(f"Product ID: {prod_id}, Name: {name_text}, Price: {price_text}")

# 2. 使用命名空间字典进行查找 (更推荐的方式,尤其是当命名空间前缀在XML中不固定时)
# 需要创建一个字典,将前缀映射到URI
namespaces = {
    'd': "http://default.com/ns", # 'd' 是我们自己定义的别名,可以随意取
    'p': "http://products.com/ns"
}

print("\n--- 使用命名空间字典 ---")
# findall() 和 find() 方法可以接受一个命名空间字典作为第二个参数
# 这样,你就可以使用带有前缀的标签名进行查找了
for item in root.findall('p:item', namespaces):
    # 获取带命名空间的属性,同样需要使用前缀
    prod_id = item.get(f"{{{namespaces['p']}}}id") # 或者更直接的 item.get('{http://products.com/ns}id')

    prod_name_element = item.find('p:name', namespaces)
    price_element = item.find('d:price', namespaces) # price在默认命名空间下,所以用'd'

    name_text = prod_name_element.text if prod_name_element is not None else "N/A"
    price_text = price_element.text if price_element is not None else "N/A"
    print(f"Product ID: {prod_id}, Name: {name_text}, Price: {price_text}")

关键点:

  • URI是核心: 无论XML中是否使用前缀,
    ElementTree
    都以其完整的URI来识别命名空间。
  • 默认命名空间: 如果XML文档有默认命名空间(
    xmlns="http://..."
    ),那么没有前缀的元素都会被归到这个命名空间下。在
    ElementTree
    内部,它们同样会被表示为
    {URI}tag_name
  • 命名空间字典: 使用
    findall()
    find()
    时,传入一个命名空间字典
    {prefix: uri}
    是一个非常好的实践。这样你的查询字符串可以更接近原始XML中的标签名,可读性更好,也更容易适应命名空间前缀变化的情况。

总之,理解

ElementTree
处理命名空间的方式,并灵活运用命名空间字典,就能让你在处理带命名空间的XML时游刃有余。当然,
lxml
在XPath中对命名空间的处理会更强大和灵活,但对于一般需求,
ElementTree
的方式也足够了。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

410

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

638

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

362

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

263

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

630

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

562

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

670

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

618

2023.09.22

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号