代码拆解
python
element_tree = ET.parse(os.path.join(dirpath_element, file)) # 1. 解析XML文件
root = element_tree.getroot() # 2. 获取根元素
Obj = root.find(element) # 3. 查找子元素 → Obj
Obj 是什么?
Obj 是一个 xml.etree.ElementTree.Element 对象,表示找到的第一个匹配元素。
python
import xml.etree.ElementTree as ET
import os
# 假设文件内容:
# <library>
# <book id="001"><title>三体</title></book>
# <book id="002"><title>流浪地球</title></book>
# </library>
element_tree = ET.parse('books.xml')
root = element_tree.getroot() # root 是 <library> 元素
# 假设 element = 'book'
element = 'book'
Obj = root.find(element) # Obj 是第一个 <book> 元素
print(type(Obj)) # <class 'xml.etree.ElementTree.Element'>
print(Obj) # <Element 'book' at 0x...>
print(Obj.tag) # 'book'
print(Obj.attrib) # {'id': '001'}
print(Obj.find('title').text) # '三体'
核心属性与方法
Obj 作为 Element 对象,包含:
| 属性/方法 | 说明 | 示例 |
|---|---|---|
Obj.tag |
标签名 | 'book' |
Obj.attrib |
属性字典 | {'id': '001'} |
Obj.text |
文本内容 | None 或 '内容' |
Obj.tail |
结束标签后的文本 | 通常 None |
Obj.find('tag') |
查找第一个子元素 | 返回 Element 或 None |
Obj.findall('tag') |
查找所有匹配子元素 | 返回列表 |
Obj.iter() |
递归遍历所有后代 | 生成器 |
Obj.get('attr') |
获取属性值 | '001' |
Obj.set('attr', 'val') |
设置属性 | 修改XML |
Obj.items() |
获取所有属性 | [('id', '001')] |
list(Obj) |
获取所有直接子元素 | [<Element>, ...] |
完整示例
python
import xml.etree.ElementTree as ET
xml_content = '''<?xml version="1.0"?>
<library location="北京">
<book id="001" category="科幻">
<title>三体</title>
<author>刘慈欣</author>
<price>59.00</price>
</book>
<book id="002" category="科幻">
<title>流浪地球</title>
<author>刘慈欣</author>
<price>45.00</price>
</book>
</library>
'''
# 写入临时文件测试
with open('test.xml', 'w', encoding='utf-8') as f:
f.write(xml_content)
# 你的代码逻辑
dirpath_element = '.'
file = 'test.xml'
element = 'book' # 要查找的标签名
element_tree = ET.parse(os.path.join(dirpath_element, file))
root = element_tree.getroot()
Obj = root.find(element) # ← 查找第一个 <book>
# ========== Obj 的详细解析 ==========
print("=" * 50)
print(f"1. Obj 类型: {type(Obj)}")
print(f"2. Obj 标签: {Obj.tag!r}")
print(f"3. Obj 属性: {Obj.attrib}")
print(f"4. Obj 直接子元素数量: {len(list(Obj))}")
print("\n5. 遍历 Obj 的子元素:")
for child in Obj:
print(f" <{child.tag}>: {child.text!r}")
print("\n6. 获取特定子元素:")
title_elem = Obj.find('title')
print(f" title_elem.text = {title_elem.text!r}")
print("\n7. 获取属性:")
print(f" id = {Obj.get('id')}")
print(f" category = {Obj.get('category')}")
print("\n8. items() 方法:")
print(f" {Obj.items()}")
# 清理
import os
os.remove('test.xml')
输出:
==================================================
1. Obj 类型: <class 'xml.etree.ElementTree.Element'>
2. Obj 标签: 'book'
3. Obj 属性: {'id': '001', 'category': '科幻'}
4. Obj 直接子元素数量: 3
5. 遍历 Obj 的子元素:
<title>: '三体'
<author>: '刘慈欣'
<price>: '59.00'
6. 获取特定子元素:
title_elem.text = '三体'
7. 获取属性:
id = 001
category = 科幻
8. items() 方法:
[('id', '001'), ('category', '科幻')]
重要注意事项
1. 找不到元素时返回 None
python
Obj = root.find('movie') # XML 中没有 <movie>
print(Obj) # None
# 必须先判断,否则报错
if Obj is not None:
print(Obj.text)
else:
print("未找到元素")
2. find() vs findall() 的区别
python
# find() - 只返回第一个匹配
Obj = root.find('book') # 第一个 <book> 元素
print(Obj.get('id')) # '001'
# findall() - 返回所有匹配的列表
books = root.findall('book') # [<book id="001">, <book id="002">]
print(len(books)) # 2
for book in books:
print(book.get('id')) # '001', '002'
3. XPath 支持
python
# 查找特定属性
Obj = root.find(".//book[@id='002']") # id=002 的 book
# 查找任意位置的元素
Obj = root.find(".//author") # 第一个 <author>(任意层级)
可视化结构
element_tree (ElementTree 对象)
└── getroot() → root (Element 对象: <library>)
└── find('book') → Obj (Element 对象: 第一个 <book>)
├── tag: 'book'
├── attrib: {'id': '001', 'category': '科幻'}
├── text: None(因为文本在子元素中)
└── 子元素列表:
├── <title> → text: '三体'
├── <author> → text: '刘慈欣'
└── <price> → text: '59.00'
总结
| 变量 | 类型 | 代表含义 |
|---|---|---|
element_tree |
ElementTree |
整个 XML 文档树 |
root |
Element |
根元素(如 <library>) |
Obj |
Element |
找到的第一个匹配子元素 |
Obj 就是 XML 中的一个元素节点,你可以用它来:
-
读取数据(
Obj.text,Obj.get(),Obj.find()) -
修改数据(
Obj.set(),Obj.text = ...) -
继续查找子元素(
Obj.find(),Obj.findall()) -
遍历子树(
Obj.iter())