文章目錄
- 你的 XML 數據
- 解析 XML
- ----------------------------
- 1. 獲取 mlt 根元素的屬性
- ----------------------------
- ----------------------------
- 2. 獲取 chain 元素的屬性
- ----------------------------
- ----------------------------
- 3. 獲取所有 property 的值
- ----------------------------
- ----------------------------
- 4. 獲取所有視頻流信息(擴展示例)
- ----------------------------
- 根據上面的代碼,報錯'lxml.etree._Element' object has no attribute 'getroot' 'lxml.etree._ElementTree' object has no attribute 'get'
- ===================================
- 正確解析方式選擇(二選一):
- ===================================
- 方案一:直接解析為 Element (適用于字符串數據)
- 方案二:使用 ElementTree (適用于文件解析)
- 如果是文件路徑:
- tree = etree.parse("your_file.xml")
- root = tree.getroot() # 這才是正確獲取根元素的方式
- ===================================
- 錯誤點分析:
- ===================================
- 錯誤用法示例:
- tree = etree.fromstring(xml_data) # 返回的是 Element
- root = tree.getroot() # ? Element 沒有 getroot() 方法
- ===================================
- 正確使用示范:
- ===================================
- 1. 獲取根元素屬性
- 2. 訪問子元素
- 3. 獲取 property 值的推薦方式
- 錯誤:fromstring 返回的是 Element,沒有 getroot()
- 正確:直接使用
- 錯誤:在 ElementTree 對象上直接訪問屬性
- 正確:先獲取根元素
- 危險:直接訪問可能不存在的元素
- 安全:添加空值判斷
- 字符串數據解析
- 文件解析
- 依據上面回答,采用root = etree.fromstring(xml_data) 的方式,如何遍歷根下面的所有子節點
- 解析 XML 獲取根元素
- ----------------------------
- 方法一:直接遍歷子元素
- ----------------------------
- ----------------------------
- 方法二:通過 XPath 獲取所有子節點
- ----------------------------
- ----------------------------
- 方法三:遞歸遍歷所有后代節點
- ----------------------------
- 只獲取 property 節點
- 獲取名字包含 'media' 的屬性節點
- media_props = root.xpath('//property[contains(@name, "media")]') print("\n包含 'media' 的屬性:") for p in media_props: print(f"{p.get('name')}: {p.text}") 4. 輸出結果示例 text 復制 所有直接子節點: 標簽名: chain 屬性: {'id': 'chain0', 'title': 'Shotcut version 25.03.14', 'out': '00:00:31.467'} 文本內容: 無
- 將屬性值轉換為 Python 類型
以下是使用 Python 的 lxml 庫解析并提取 XML 數據的完整示例代碼:
python
復制
from lxml import etree
你的 XML 數據
xml_data = ‘’'<?xml version="1.0" encoding="utf-8"?>
‘’’
解析 XML
root = etree.fromstring(xml_data.encode(‘utf-8’))
----------------------------
1. 獲取 mlt 根元素的屬性
----------------------------
mlt_attributes = {
‘version’: root.get(‘version’),
‘title’: root.get(‘title’),
‘LC_NUMERIC’: root.get(‘LC_NUMERIC’)
}
print(“MLT 根元素屬性:”)
for k, v in mlt_attributes.items():
print(f"{k}: {v}")
----------------------------
2. 獲取 chain 元素的屬性
----------------------------
chain = root.find(‘chain’)
chain_info = {
‘id’: chain.get(‘id’),
‘title’: chain.get(‘title’),
‘duration’: chain.get(‘out’)
}
print(“\nChain 元素屬性:”)
for k, v in chain_info.items():
print(f"{k}: {v}")
----------------------------
3. 獲取所有 property 的值
----------------------------
print(“\n關鍵 Property 列表:”)
properties = [
‘length’, ‘resource’,
‘meta.media.width’, ‘meta.media.height’,
‘meta.media.0.codec.name’, ‘creation_time’
]
for prop_name in properties:
# 使用 XPath 精確查找
prop = chain.xpath(f’property[@name=“{prop_name}”]')
if prop:
print(f"{prop_name}: {prop[0].text}“)
else:
print(f”{prop_name}: Not Found")
----------------------------
4. 獲取所有視頻流信息(擴展示例)
----------------------------
print(“\n視頻流詳細信息:”)
for i in range(2): # 根據示例數據有 2 個流
stream_type = chain.xpath(f’property[@name=“meta.media.{i}.stream.type”]‘)
if stream_type:
stream_type = stream_type[0].text
codec_name = chain.xpath(f’property[@name=“meta.media.{i}.codec.name”]’)[0].text
print(f"Stream {i}:“)
print(f” Type: {stream_type}“)
print(f” Codec: {codec_name}")
if stream_type == 'video':resolution = f"{chain.xpath(f'property[@name="meta.media.{i}.codec.width"]')[0].text}x" \f"{chain.xpath(f'property[@name="meta.media.{i}.codec.height"]')[0].text}"print(f" Resolution: {resolution}")
代碼說明:
XML 解析:使用 etree.fromstring() 解析 XML 字符串
根元素屬性:直接通過元素的 get() 方法獲取屬性值
子元素定位:
find() 用于獲取第一個匹配的子元素
xpath() 用于復雜查詢(支持完整的 XPath 1.0 語法)
屬性提取:
使用 element.get(‘attribute_name’) 獲取元素屬性
使用 element.text 獲取元素文本內容
輸出示例:
text
復制
MLT 根元素屬性:
version: 7.24.0
title: Shotcut version 25.03.14
LC_NUMERIC: C
Chain 元素屬性:
id: chain0
title: Shotcut version 25.03.14
duration: 00:00:31.467
關鍵 Property 列表:
length: 00:00:31.500
resource: E:/test/video/test_game_video/7.mp4
meta.media.width: 1920
meta.media.height: 1080
meta.media.0.codec.name: h264
creation_time: 2025-02-05T07:19:51
視頻流詳細信息:
Stream 0:
Type: video
Codec: h264
Resolution: 1920x1080
Stream 1:
Type: audio
Codec: aac
注意事項:
對于需要處理命名空間的 XML,需要注冊命名空間
XPath 表達式中的屬性值匹配要完全一致(包括大小寫)
使用 .encode(‘utf-8’) 確保正確處理中文字符
使用防御性編程檢查元素是否存在(示例中簡化為直接訪問,實際生產環境建議添加校驗)
如果需要處理更復雜的 XML 結構或需要其他特定數據提取方式,可以進一步擴展這些基礎方法。
根據上面的代碼,報錯’lxml.etree._Element’ object has no attribute ‘getroot’ ‘lxml.etree._ElementTree’ object has no attribute ‘get’
你遇到的錯誤是由于混淆了兩種不同的 XML 解析對象類型:Element 和 ElementTree。以下是完整解決方案:
python
復制
from lxml import etree
xml_data = ‘’'<?xml version="1.0" encoding="utf-8"?>
‘’’
===================================
正確解析方式選擇(二選一):
===================================
方案一:直接解析為 Element (適用于字符串數據)
root = etree.fromstring(xml_data.encode(‘utf-8’)) # 直接得到根元素
方案二:使用 ElementTree (適用于文件解析)
如果是文件路徑:
tree = etree.parse(“your_file.xml”)
root = tree.getroot() # 這才是正確獲取根元素的方式
===================================
錯誤點分析:
===================================
錯誤用法示例:
tree = etree.fromstring(xml_data) # 返回的是 Element
root = tree.getroot() # ? Element 沒有 getroot() 方法
===================================
正確使用示范:
===================================
1. 獲取根元素屬性
print(“根元素屬性:”)
print(f"版本: {root.get(‘version’)}“) # ? 正確訪問方式
print(f"標題: {root.get(‘title’)}”)
2. 訪問子元素
chain = root.find(‘chain’) # 返回 Element 對象
if chain is not None: # 安全判斷
print(“\nChain 元素屬性:”)
print(f"ID: {chain.get(‘id’)}“)
print(f"時長: {chain.get(‘out’)}”)
3. 獲取 property 值的推薦方式
def get_property(element, name):
“”“安全獲取 property 值的輔助函數”“”
prop = element.xpath(f’property[@name=“{name}”]')
return prop[0].text if prop else None
if chain is not None:
print(“\n關鍵屬性值:”)
print(f"視頻長度: {get_property(chain, ‘length’)}“)
print(f"文件路徑: {get_property(chain, ‘resource’)}”)
print(f"分辨率: {get_property(chain, ‘meta.media.width’)}x{get_property(chain, ‘meta.media.height’)}")
關鍵區別說明:
方法 返回類型 適用場景 獲取根元素方式
etree.fromstring() Element 解析字符串/字節數據 直接返回根元素
etree.parse() ElementTree 解析文件/文件類對象 需要 .getroot()
常見錯誤場景分析:
錯誤調用 getroot():
python
復制
錯誤:fromstring 返回的是 Element,沒有 getroot()
root = etree.fromstring(xml_data).getroot() # ? 會報錯
正確:直接使用
root = etree.fromstring(xml_data) # ?
混淆對象類型:
python
復制
錯誤:在 ElementTree 對象上直接訪問屬性
tree = etree.parse(“file.xml”)
print(tree.get(‘version’)) # ? ElementTree 沒有 get() 方法
正確:先獲取根元素
root = tree.getroot() # ?
print(root.get(‘version’))
未做空值判斷:
python
復制
危險:直接訪問可能不存在的元素
print(root.find(‘non_exist_tag’).get(‘attr’)) # ? 可能拋出 AttributeError
安全:添加空值判斷
element = root.find(‘non_exist_tag’)
if element is not None:
print(element.get(‘attr’))
最佳實踐建議:
統一使用方案:
python
復制
字符串數據解析
def parse_xml_string(xml_str):
root = etree.fromstring(xml_str)
# 后續處理 root…
文件解析
def parse_xml_file(file_path):
tree = etree.parse(file_path)
root = tree.getroot()
# 后續處理 root…
使用類型檢查:
python
復制
print(type(root)) # 輸出:<class ‘lxml.etree._Element’>
print(type(etree.parse(“file.xml”))) # 輸出:<class ‘lxml.etree._ElementTree’>
增強錯誤處理:
python
復制
try:
root = etree.fromstring(xml_data)
chain = root.find(‘chain’)
if chain is None:
raise ValueError(“Chain element not found”)
resource = get_property(chain, 'resource')
print(f"資源路徑: {resource}")
except etree.XMLSyntaxError as e:
print(f"XML 解析錯誤: {e}“)
except Exception as e:
print(f"其他錯誤: {e}”)
通過以上修正和規范,你可以避免這類對象類型錯誤,并建立更健壯的 XML 解析代碼結構。
依據上面回答,采用root = etree.fromstring(xml_data) 的方式,如何遍歷根下面的所有子節點
以下是使用 lxml 的 Element 對象遍歷根節點下所有子節點的完整方法,通過逐步分析實現:
- 基礎遍歷方法
python
復制
from lxml import etree
xml_data = ‘’‘<?xml version="1.0" encoding="utf-8"?>
00:00:31.500
E:/test/video/test_game_video/7.mp4
’‘’
解析 XML 獲取根元素
root = etree.fromstring(xml_data.encode(‘utf-8’))
----------------------------
方法一:直接遍歷子元素
----------------------------
print(“所有直接子節點:”)
for child in root.iterchildren():
print(f"標簽名: {child.tag}“)
print(f"屬性: {child.attrib}”)
print(f"文本內容: {child.text.strip() if child.text else ‘無’}“)
print(”-" * 30)
2. 擴展遍歷方式
2.1 使用 XPath 定位
python
復制
----------------------------
方法二:通過 XPath 獲取所有子節點
----------------------------
all_children = root.xpath(‘./*’) # 獲取直接子元素
print(f"共找到 {len(all_children)} 個直接子節點")
for idx, element in enumerate(all_children, 1):
print(f"\n節點 {idx}:“)
print(f"標簽類型: {element.tag}”)
print(f"屬性列表: {element.keys()}“)
if element.attrib.get(‘name’):
print(f"特殊屬性 name 的值: {element.get(‘name’)}”)
2.2 深度遍歷(遞歸所有后代)
python
復制
----------------------------
方法三:遞歸遍歷所有后代節點
----------------------------
def traverse(element, depth=0):
prefix = " " * depth
print(f"{prefix}層級 {depth}: [{element.tag}]")
for child in element.iterchildren():
traverse(child, depth + 1)
print(“\n遞歸遍歷結構:”)
traverse(root)
3. 針對特定場景的遍歷
3.1 過濾特定標簽
python
復制
只獲取 property 節點
properties = root.xpath(‘//property’)
print(f"\n找到 {len(properties)} 個 property 節點:“)
for prop in properties:
print(f"屬性名: {prop.get(‘name’)} => 值: {prop.text}”)
3.2 帶條件的遍歷
python
復制
獲取名字包含 ‘media’ 的屬性節點
media_props = root.xpath(‘//property[contains(@name, “media”)]’)
print(“\n包含 ‘media’ 的屬性:”)
for p in media_props:
print(f"{p.get(‘name’)}: {p.text}")
4. 輸出結果示例
text
復制
所有直接子節點:
標簽名: chain
屬性: {‘id’: ‘chain0’, ‘title’: ‘Shotcut version 25.03.14’, ‘out’: ‘00:00:31.467’}
文本內容: 無
共找到 1 個直接子節點
節點 1:
標簽類型: chain
屬性列表: [‘id’, ‘title’, ‘out’]
特殊屬性 name 的值: None
遞歸遍歷結構:
層級 0: [mlt]
層級 1: [chain]
層級 2: [property]
層級 2: [property]
找到 2 個 property 節點:
屬性名: length => 值: 00:00:31.500
屬性名: resource => 值: E:/test/video/test_game_video/7.mp4
包含 ‘media’ 的屬性:
meta.media.width: 1920
meta.media.height: 1080
5. 關鍵要點總結
方法 特點 適用場景
iterchildren() 直接訪問子元素,內存效率高 只需要直接子節點時
XPath ./* 靈活,可配合復雜條件 需要過濾或特殊定位時
遞歸遍歷 獲取完整節點結構 需要分析整體文檔結構時
XPath 條件過濾 精準定位特定特征節點 提取特定數據時
6. 高級技巧
6.1 處理命名空間
如果 XML 包含命名空間:
python
復制
ns = {‘mlt’: ‘http://example.org/ns’} # 替換為實際的命名空間
chains = root.xpath(‘//mlt:chain’, namespaces=ns)
6.2 性能優化
對于大型 XML 使用 iterparse() 流式解析:
python
復制
context = etree.iterparse(StringIO(xml_data), events=(“start”, “end”))
for event, elem in context:
if event == “start” and elem.tag == “property”:
print(f"找到屬性: {elem.get(‘name’)}")
elem.clear() # 及時清理已處理元素
6.3 數據類型轉換
python
復制
將屬性值轉換為 Python 類型
width = int(root.xpath(‘//property[@name=“meta.media.width”]/text()’)[0])
is_progressive = bool(root.xpath(‘//property[@name=“meta.media.progressive”]/text()’)[0] == ‘1’)
通過以上方法,你可以根據具體需求選擇最適合的遍歷方式。實際應用中建議結合 try-except 塊處理可能的節點缺失情況。