一、xmltodict库核心概述
1.1 库的用途
xmltodict是一款轻量级的Python库,核心功能是实现XML字符串与Python字典(dict)之间的双向转换,同时支持将Python字典反向生成为XML格式数据。借助该库,开发者无需编写复杂的XML解析代码(如DOM、SAX解析逻辑),就能像操作普通字典一样处理XML数据,极大降低了XML数据处理的门槛,广泛应用于接口数据解析、配置文件读取、数据格式转换等场景。

1.2 工作原理
xmltodict的底层基于Python内置的xml.parsers.expat解析器,采用事件驱动的解析方式处理XML数据。在解析XML时,它会遍历XML文档的各个节点(元素、属性、文本),将XML元素标签映射为字典的键,元素属性以@前缀标识的键存储,元素内的文本内容则存储在#text键中;反向生成XML时,会根据字典的键值结构,按照XML的语法规则拼接成对应的XML字符串。
1.3 优缺点分析
优点
- 操作简单:将XML解析为字典后,可通过键值对快速访问数据,学习成本极低。
- 轻量高效:依赖少,解析速度快,适合处理中小型XML文档。
- 兼容性强:支持自定义命名空间处理、属性优先级设置等高级功能,满足多样化需求。
- 双向转换:既可以解析XML为字典,也能将字典生成为标准XML,功能完整。
缺点
- 内存消耗:解析大型XML文档时,会将整个文档加载到内存中,可能引发内存溢出问题。
- 结构限制:对于嵌套层级极深的XML,转换后的字典结构会变得复杂,可读性下降。
1.4 许可证类型
xmltodict采用MIT License开源许可证,这意味着开发者可以自由地使用、复制、修改、合并、出版发行、散布、授权和/或销售该软件的副本,同时也可以将软件嵌入到其他商业软件中,只需保留原作者的版权声明即可。
二、xmltodict库安装与环境准备
2.1 安装方法
xmltodict是Python第三方库,可通过pip包管理工具一键安装,支持Python 2.7和Python 3.x版本,安装命令如下:
pip install xmltodict安装完成后,可在Python交互式环境中执行以下代码验证是否安装成功:
import xmltodict
print(xmltodict.__version__)若输出类似0.13.0的版本号,则说明安装成功。
2.2 环境要求
- Python版本:Python 2.7 或 Python 3.4+
- 依赖库:无额外强制依赖,仅依赖Python标准库中的
xml.parsers.expat
三、xmltodict库基础使用教程
3.1 核心函数介绍
xmltodict的核心功能由两个函数实现,分别是parse()和unparse(),具体说明如下:
| 函数名 | 功能描述 | 常用参数 |
|–|-|-|
| xmltodict.parse(xml_input, **kwargs) | 将XML字符串或文件对象解析为Python字典 | xml_input:XML字符串/文件对象;encoding:编码格式,默认utf-8;process_namespaces:是否处理命名空间,默认False;attr_prefix:属性键前缀,默认@;cdata_key:CDATA段键名,默认#text |
| xmltodict.unparse(dict_input, **kwargs) | 将Python字典反向生成为XML字符串 | dict_input:待转换的Python字典;encoding:编码格式,默认utf-8;pretty:是否格式化输出,默认False;indent:格式化缩进字符,默认(两个空格) |
3.2 基础案例1:XML字符串解析为字典
本案例演示如何将一个简单的XML字符串解析为Python字典,并通过键值对访问XML中的数据。
# 导入xmltodict库
import xmltodict
# 定义一个简单的XML字符串
xml_str = """
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
"""
# 将XML字符串解析为Python字典
dict_data = xmltodict.parse(xml_str)
# 打印转换后的字典
print("转换后的字典结构:")
print(dict_data)
print("\n")
# 访问字典中的数据
# 1. 获取第一个book的分类
first_book_category = dict_data["bookstore"]["book"][0]["@category"]
print("第一本书的分类:", first_book_category)
# 2. 获取第二本书的标题
second_book_title = dict_data["bookstore"]["book"][1]["title"]
print("第二本书的标题:", second_book_title)
# 3. 获取第一本书的价格
first_book_price = dict_data["bookstore"]["book"][0]["price"]
print("第一本书的价格:", first_book_price)代码说明
- 首先导入
xmltodict库,定义一个包含两本图书信息的XML字符串,其中<book>标签包含category属性,子标签包括title、author等。 - 使用
xmltodict.parse()函数将XML字符串转换为字典,XML的根节点bookstore成为字典的顶层键,子节点book则以列表形式存储(因为存在多个<book>元素)。 - XML元素的属性会以
@属性名的形式作为字典的键,例如@category对应<book>标签的category属性。 - 通过字典的键值索引,可快速获取目标数据,例如
dict_data["bookstore"]["book"][0]对应第一本图书的所有信息。
运行结果
转换后的字典结构:
{'bookstore': {'book': [{'@category': 'COOKING', 'title': {'@lang': 'en', '#text': 'Everyday Italian'}, 'author': 'Giada De Laurentiis', 'year': '2005', 'price': '30.00'}, {'@category': 'CHILDREN', 'title': {'@lang': 'en', '#text': 'Harry Potter'}, 'author': 'J K. Rowling', 'year': '2005', 'price': '29.99'}]}}
第一本书的分类: COOKING
第二本书的标题: {'@lang': 'en', '#text': 'Harry Potter'}
第一本书的价格: 30.003.3 基础案例2:Python字典生成XML字符串
本案例演示如何将Python字典反向转换为XML字符串,并通过参数控制XML的格式化输出。
import xmltodict
# 定义一个Python字典,模拟图书信息
book_dict = {
"bookstore": {
"book": [
{
"@category": "COOKING",
"title": {
"@lang": "en",
"#text": "Everyday Italian"
},
"author": "Giada De Laurentiis",
"year": "2005",
"price": "30.00"
},
{
"@category": "CHILDREN",
"title": {
"@lang": "en",
"#text": "Harry Potter"
},
"author": "J K. Rowling",
"year": "2005",
"price": "29.99"
}
]
}
}
# 将字典转换为XML字符串(无格式化)
xml_str_no_pretty = xmltodict.unparse(book_dict)
print("无格式化的XML字符串:")
print(xml_str_no_pretty)
print("\n")
# 将字典转换为XML字符串(带格式化,缩进为4个空格)
xml_str_pretty = xmltodict.unparse(book_dict, pretty=True, indent=" ")
print("格式化后的XML字符串:")
print(xml_str_pretty)代码说明
- 定义一个与上例XML结构对应的Python字典,其中属性以
@属性名作为键,文本内容以#text作为键,这是xmltodict识别属性和文本的约定。 - 使用
xmltodict.unparse()函数将字典转换为XML字符串,默认情况下(pretty=False)生成的XML是紧凑格式,无换行和缩进。 - 当设置
pretty=True时,生成的XML会自动换行和缩进,indent参数可指定缩进的字符(如4个空格),提升XML的可读性。
运行结果
无格式化的XML字符串:
<?xml version="1.0" encoding="utf-8"?><bookstore><book category="COOKING"><title lang="en">Everyday Italian</title><author>Giada De Laurentiis</author><year>2005</year><price>30.00</price></book><book category="CHILDREN"><title lang="en">Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book></bookstore>
格式化后的XML字符串:
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>3.4 基础案例3:读取XML文件并解析
在实际开发中,XML数据常以文件形式存储,本案例演示如何读取本地XML文件并解析为字典。
首先创建一个名为books.xml的文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book category="BUSINESS">
<title lang="en">XML Developer's Guide</title>
<author>Robert Richards</author>
<year>2002</year>
<price>44.95</price>
</book>
<book category="TECHNOLOGY">
<title lang="en">Python Crash Course</title>
<author>Eric Matthes</author>
<year>2019</year>
<price>29.95</price>
</book>
</bookstore>然后编写Python代码读取并解析该文件:
import xmltodict
# 打开XML文件并解析为字典
with open("books.xml", "r", encoding="utf-8") as f:
# 直接将文件对象传入parse函数
dict_data = xmltodict.parse(f)
# 遍历所有图书信息并打印
print("图书列表:")
for book in dict_data["bookstore"]["book"]:
print(f"分类:{book['@category']}")
print(f"标题:{book['title']['#text']}")
print(f"语言:{book['title']['@lang']}")
print(f"作者:{book['author']}")
print(f"年份:{book['year']}")
print(f"价格:{book['price']}")
print("-" * 20)代码说明
- 使用Python的
with open()语句以只读模式打开books.xml文件,指定编码为utf-8,避免中文乱码。 xmltodict.parse()函数支持直接传入文件对象,无需手动读取文件内容,简化了代码流程。- 通过遍历
dict_data["bookstore"]["book"]列表,可逐个获取每本图书的属性和子节点数据,并格式化输出。
运行结果
图书列表:
分类:BUSINESS
标题:XML Developer's Guide
语言:en
作者:Robert Richards
年份:2002
价格:44.95
--
分类:TECHNOLOGY
标题:Python Crash Course
语言:en
作者:Eric Matthes
年份:2019
价格:29.95
--四、xmltodict库进阶使用技巧
4.1 处理XML命名空间
在复杂的XML文档中,命名空间(Namespace)是常见的元素,用于避免标签名冲突。xmltodict支持通过process_namespaces参数处理命名空间,本案例演示如何解析带命名空间的XML。
import xmltodict
# 定义带命名空间的XML字符串
xml_with_ns = """
<root xmlns:ns="http://example.com/ns">
<ns:user id="1001">
<ns:name>Alice</ns:name>
<ns:age>25</ns:age>
</ns:user>
<ns:user id="1002">
<ns:name>Bob</ns:name>
<ns:age>30</ns:age>
</ns:user>
</root>
"""
# 不处理命名空间的情况
dict_no_ns = xmltodict.parse(xml_with_ns)
print("不处理命名空间的结果:")
print(dict_no_ns)
print("\n")
# 处理命名空间的情况(process_namespaces=True)
dict_with_ns = xmltodict.parse(xml_with_ns, process_namespaces=True)
print("处理命名空间的结果:")
print(dict_with_ns)
print("\n")
# 自定义命名空间前缀映射
namespace_map = {"http://example.com/ns": "user"}
dict_custom_ns = xmltodict.parse(
xml_with_ns,
process_namespaces=True,
namespaces=namespace_map
)
print("自定义命名空间前缀的结果:")
print(dict_custom_ns)代码说明
- 定义的XML字符串中包含命名空间
xmlns:ns="http://example.com/ns",所有子标签均以ns:为前缀。 - 当
process_namespaces=False(默认值)时,解析后的字典键会保留命名空间前缀(如ns:user)。 - 当
process_namespaces=True时,xmltodict会自动移除命名空间前缀,直接使用标签名作为键。 - 通过
namespaces参数可传入自定义的命名空间映射字典,将命名空间URI映射为更简洁的前缀,方便数据访问。
运行结果
不处理命名空间的结果:
{'root': {'@xmlns:ns': 'http://example.com/ns', 'ns:user': [{'@id': '1001', 'ns:name': 'Alice', 'ns:age': '25'}, {'@id': '1002', 'ns:name': 'Bob', 'ns:age': '30'}]}}
处理命名空间的结果:
{'root': {'user': [{'@id': '1001', 'name': 'Alice', 'age': '25'}, {'@id': '1002', 'name': 'Bob', 'age': '30'}]}}
自定义命名空间前缀的结果:
{'root': {'user:user': [{'@id': '1001', 'user:name': 'Alice', 'user:age': '25'}, {'@id': '1002', 'user:name': 'Bob', 'user:age': '30'}]}}4.2 处理CDATA段
XML中的CDATA段用于存储不需要转义的文本内容(如包含<、>、&等特殊字符的文本),xmltodict默认将CDATA段的内容存储在#text键中,本案例演示如何解析包含CDATA段的XML。
import xmltodict
# 定义包含CDATA段的XML字符串
xml_with_cdata = """
<article>
<title>Python & XML</title>
<content><![CDATA[这是一篇关于Python解析XML的文章,包含特殊字符:< > & " ']]></content>
</article>
"""
# 解析XML字符串
dict_data = xmltodict.parse(xml_with_cdata)
# 访问CDATA段内容
title = dict_data["article"]["title"]
content = dict_data["article"]["content"]["#text"]
print(f"文章标题:{title}")
print(f"文章内容:{content}")
# 反向生成包含CDATA的XML
article_dict = {
"article": {
"title": "Python & XML",
"content": {
"#cdata-section": "这是一篇关于Python解析XML的文章,包含特殊字符:< > & \" '"
}
}
}
xml_str = xmltodict.unparse(article_dict, pretty=True)
print("\n生成的包含CDATA的XML:")
print(xml_str)代码说明
- XML中的
<content>标签包含CDATA段,存储了带有特殊字符的文本,这些字符无需转义。 - 解析后,CDATA段的内容会被存储在
#text键中,可直接通过该键获取文本内容。 - 反向生成包含CDATA的XML时,需要在字典中使用
#cdata-section键,对应的值会被包装为CDATA段。
运行结果
文章标题:Python & XML
文章内容:这是一篇关于Python解析XML的文章,包含特殊字符:< > & " '
生成的包含CDATA的XML:
<?xml version="1.0" encoding="utf-8"?>
<article>
<title>Python & XML</title>
<content><![CDATA[这是一篇关于Python解析XML的文章,包含特殊字符:< > & " ']]></content>
</article>4.3 自定义解析参数
xmltodict提供了多个自定义参数,可根据需求调整解析行为,本案例演示常用参数的使用方法。
import xmltodict
xml_str = """
<data>
<item id="1">A</item>
<item id="2">B</item>
</data>
"""
# 自定义属性前缀(将默认的@改为attr_)
dict_custom_attr = xmltodict.parse(xml_str, attr_prefix="attr_")
print("自定义属性前缀的结果:")
print(dict_custom_attr)
print("\n")
# 自定义文本键名(将默认的#text改为text)
dict_custom_text = xmltodict.parse(xml_str, cdata_key="text")
print("自定义文本键名的结果:")
print(dict_custom_text)
print("\n")
# 强制将单元素列表转换为列表(force_list参数)
# 当XML中只有一个<item>标签时,默认不会生成列表,force_list可强制生成列表
xml_single_item = """
<data>
<item id="1">A</item>
</data>
"""
# 默认解析
dict_default = xmltodict.parse(xml_single_item)
print("默认解析单元素的结果:")
print(type(dict_default["data"]["item"])) # 输出<class 'dict'>
# 强制生成列表
dict_force_list = xmltodict.parse(xml_single_item, force_list=["item"])
print("强制生成列表的结果:")
print(type(dict_force_list["data"]["item"])) # 输出<class 'list'>代码说明
attr_prefix参数:用于修改属性键的前缀,默认是@,可改为其他字符串(如attr_),避免与普通键名冲突。cdata_key参数:用于修改文本内容的键名,默认是#text,可改为更简洁的名称(如text)。force_list参数:用于指定哪些标签需要强制生成列表,即使该标签在XML中只出现一次,避免后续遍历数据时出现类型错误。
运行结果
自定义属性前缀的结果:
{'data': {'item': [{'attr_id': '1', '#text': 'A'}, {'attr_id': '2', '#text': 'B'}]}}
自定义文本键名的结果:
{'data': {'item': [{'@id': '1', 'text': 'A'}, {'@id': '2', 'text': 'B'}]}}
默认解析单元素的结果:
<class 'dict'>
强制生成列表的结果:
<class 'list'>五、xmltodict库实战案例:接口数据处理
在实际开发中,很多第三方接口会返回XML格式的数据,本案例模拟一个天气查询接口,使用xmltodict解析接口返回的XML数据,并提取关键信息。
5.1 模拟接口返回的XML数据
import xmltodict
# 模拟天气接口返回的XML数据
weather_xml = """
<weather_response>
<city>北京市</city>
<date>2024-05-20</date>
<temperature>
<max>28</max>
<min>18</min>
<unit>℃</unit>
</temperature>
<weather>晴转多云</weather>
<wind>
<direction>南风</direction>
<level>2-3级</level>
</wind>
</weather_response>
"""5.2 解析XML数据并提取信息
# 解析XML数据
weather_dict = xmltodict.parse(weather_xml)
# 提取关键天气信息
city = weather_dict["weather_response"]["city"]
date = weather_dict["weather_response"]["date"]
max_temp = weather_dict["weather_response"]["temperature"]["max"]
min_temp = weather_dict["weather_response"]["temperature"]["min"]
unit = weather_dict["weather_response"]["temperature"]["unit"]
weather = weather_dict["weather_response"]["weather"]
wind_dir = weather_dict["weather_response"]["wind"]["direction"]
wind_level = weather_dict["weather_response"]["wind"]["level"]
# 格式化输出天气信息
weather_info = f"""
{date} {city}天气信息
天气状况:{weather}
温度范围:{min_temp}{unit} - {max_temp}{unit}
风向风力:{wind_dir} {wind_level}
"""
print(weather_info)5.3 将处理后的数据生成为新的XML
# 构造新的天气字典(仅保留核心信息)
simple_weather_dict = {
"simple_weather": {
"@city": city,
"@date": date,
"weather": weather,
"temp_range": f"{min_temp}{unit} - {max_temp}{unit}"
}
}
# 生成格式化的XML字符串
simple_weather_xml = xmltodict.unparse(simple_weather_dict, pretty=True, indent=" ")
print("生成的简化天气XML:")
print(simple_weather_xml)代码说明
- 首先模拟天气接口返回的XML数据,包含城市、日期、温度、天气状况、风向风力等信息。
- 使用
xmltodict.parse()解析XML数据后,通过键值索引提取所需信息,并格式化输出为用户友好的天气报告。 - 构造一个简化的天气字典,仅保留核心信息,并使用
xmltodict.unparse()生成新的XML字符串,用于数据存储或接口转发。
运行结果
2024-05-20 北京市天气信息
天气状况:晴转多云
温度范围:18℃ - 28℃
风向风力:南风 2-3级
生成的简化天气XML:
<?xml version="1.0" encoding="utf-8"?>
<simple_weather city="北京市" date="2024-05-20">
<weather>晴转多云</weather>
<temp_range>18℃ - 28℃</temp_range>
</simple_weather>六、xmltodict库相关资源
6.1 Pypi地址
6.2 Github地址
6.3 官方文档地址
关注我,每天分享一个实用的Python自动化工具。

