一、XML 基础认知
XML(可扩展标记语言)是用于存储 / 传输结构化数据的格式,核心特点是标签可自定义,结构层级清晰。示例结构:
xml
<library> <!-- 根节点 --> <book id="1001"> <!-- 子节点,带属性 --> <title>Python编程</title> <!-- 叶子节点,带文本 --> <price>89.0</price> </book> </library>Python 中处理 XML 的主流工具是内置的xml.etree.ElementTree(简称 ET),它轻量、高效,满足绝大多数 XML 处理场景。
二、核心操作实战
1. 解析 XML(读取与查询)
解析是处理 XML 的第一步,支持从文件 / 字符串解析,重点是精准提取节点数据。
准备示例文件(book.xml)
xml
<library> <book id="1001"> <title>Python编程:从入门到实践</title> <author>埃里克·马瑟斯</author> <price>89.0</price> <category>编程</category> </book> <book id="1002"> <title>XML基础教程</title> <author>李四</author> <price>59.0</price> <category>数据格式</category> </book> </library>解析代码示例
python
运行
import xml.etree.ElementTree as ET # 1. 从文件解析XML(最常用) tree = ET.parse("book.xml") root = tree.getroot() # 获取根节点(<library>) # 2. 从字符串解析XML(适合动态生成的XML) xml_str = """ <library> <book id="1003"><title>Java编程</title><price>79.0</price></book> </library> """ root_from_str = ET.fromstring(xml_str) # 3. 基础遍历:遍历所有book节点 print("=== 基础遍历 ===") for book in root: book_id = book.get("id") # 获取节点属性 title = book.find("title").text # 查找第一个子节点并取文本 price = book.find("price").text print(f"ID: {book_id}, 标题: {title}, 价格: {price}") # 4. 进阶查询:XPath语法(精准定位) print("\n=== XPath进阶查询 ===") # 查所有价格>60的book high_price_books = root.findall(".//book[price>60]") for book in high_price_books: print(f"高价书:{book.find('title').text}") # 查id=1002的book的category category = root.find(".//book[@id='1002']/category").text print(f"ID=1002的分类:{category}")关键解析
ET.parse():从文件加载 XML,返回 Tree 对象;ET.fromstring():从字符串加载,直接返回根节点。get("属性名"):获取节点的属性值(如id)。find("节点名"):查找第一个匹配的子节点;findall():查找所有匹配节点。- XPath:进阶核心,
.//book表示递归查找所有 book 节点,[@id='1002']筛选属性,price>60筛选文本值。
2. 修改 XML(修改 / 添加 / 删除节点)
解析后常需要修改内容,比如更新值、新增节点、删除无用节点。
python
运行
import xml.etree.ElementTree as ET # 解析文件 tree = ET.parse("book.xml") root = tree.getroot() # 1. 修改节点内容/属性 book_1001 = root.find(".//book[@id='1001']") price_node = book_1001.find("price") price_node.text = "85.0" # 修改文本 price_node.set("currency", "CNY") # 添加/修改属性 # 2. 添加新节点 book_1002 = root.find(".//book[@id='1002']") publish_date = ET.Element("publish_date") # 创建新节点 publish_date.text = "2024-01-01" book_1002.append(publish_date) # 追加到子节点末尾 # 3. 删除节点 category_node = book_1002.find("category") book_1002.remove(category_node) # 4. 保存修改后的XML(指定编码避免中文乱码) tree.write( "modified_book.xml", encoding="utf-8", xml_declaration=True # 生成XML声明头(<?xml version='1.0'?>) ) print("XML修改完成,已保存为modified_book.xml")关键修改
set("属性名", "值"):给节点添加 / 更新属性(如给 price 加货币单位)。ET.Element("节点名"):创建新节点,append()/insert(索引, 节点)添加到父节点。remove(节点):删除指定子节点。tree.write():保存时务必指定encoding="utf-8",否则中文会乱码。
3. 生成 XML(从零创建)
有时需要完全手动构建 XML,而非修改现有文件。
python
运行
import xml.etree.ElementTree as ET # 1. 创建根节点 root = ET.Element("students") # 2. 创建子节点(推荐用SubElement,简化操作) # 第一个学生节点(带属性) student1 = ET.SubElement(root, "student") student1.set("id", "S001") ET.SubElement(student1, "name").text = "小明" ET.SubElement(student1, "age").text = "18" ET.SubElement(student1, "major").text = "计算机科学" # 第二个学生节点(直接指定属性) student2 = ET.SubElement(root, "student", id="S002") ET.SubElement(student2, "name").text = "小红" ET.SubElement(student2, "age").text = "19" ET.SubElement(student2, "major").text = "软件工程" # 3. 生成Tree并保存 tree = ET.ElementTree(root) tree.write( "students.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False # 空节点用<node></node>而非<node/> ) print("XML生成完成,已保存为students.xml")生成的students.xml最终效果:
xml
<?xml version='1.0' encoding='utf-8'?> <students> <student id="S001"> <name>小明</name> <age>18</age> <major>计算机科学</major> </student> <student id="S002"> <name>小红</name> <age>19</age> <major>软件工程</major> </student> </students>4. 进阶:处理 XML 命名空间
XML 命名空间(xmlns)用于避免标签名冲突(如<ns:book>),处理时需指定命名空间映射。
python
运行
import xml.etree.ElementTree as ET # 带命名空间的XML字符串 xml_with_ns = """ <library xmlns:bk="http://example.com/books"> <bk:book id="1001"> <bk:title>Python编程</bk:title> </bk:book> </library> """ root = ET.fromstring(xml_with_ns) # 定义命名空间映射(前缀→URI) ns = {"bk": "http://example.com/books"} # 必须指定namespaces参数才能查询 title = root.find(".//bk:title", namespaces=ns).text print(f"带命名空间的标题:{title}") # 输出:Python编程三、总结
- Python 处理 XML 的核心工具是内置的
xml.etree.ElementTree,无需额外安装,支持解析、修改、生成全流程。 - 解析 XML 的核心技巧:基础用
find()/findall(),进阶用 XPath;修改 XML 后保存时需指定encoding="utf-8"避免中文乱码。 - 处理带命名空间的 XML 时,必须通过
namespaces参数映射前缀与 URI,否则无法正确定位节点。