python3使用lxml解析xml時踩坑記錄

文章目錄

  • 你的 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 對象遍歷根節點下所有子節點的完整方法,通過逐步分析實現:

  1. 基礎遍歷方法
    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 塊處理可能的節點缺失情況。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74127.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74127.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74127.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【DeepSeek 學c++】dynamic_cast 原理

用于向下轉化。 父類引用指向指類對象 假設父親是a, 子類是b. B* pb new B; 子類對象 A* pa 父類引用指向子類對象&#xff0c; 那么向上轉化 Apa pb 這個是自動完成的&#xff0c;隱式轉化&#xff0c;不需要dynamic_cast 向下轉化指的是 A pa new B。 這個是指向子類對象…

c++ 數組索引越界檢查

用 c 編寫了一些程序&#xff0c;發現 c 不會自動檢查數組的索引越界問題。有時候程序運行錯誤&#xff0c;提示的錯誤信息莫名其妙&#xff0c;但很可能是某個數組越界的問題。 例如&#xff1a; #include <iostream>int main() {double arr[5] {1.1, 2.2, 3.3, 4.4,…

Touch Diver:Weart為XR和機器人遙操作專屬設計的觸覺反饋動捕手套

在虛擬現實&#xff08;VR&#xff09;和擴展現實&#xff08;XR&#xff09;領域&#xff0c;觸覺反饋技術正逐漸成為提升沉浸感和交互體驗的重要因素。Weart作為這一領域的創新者&#xff0c;憑借其TouchDIVER Pro和TouchDIVER G1觸覺手套&#xff0c;為用戶帶來了高度逼真的…

基于deepseek的智能語音客服【第二講】后端異步接口調用封裝

本篇內容主要講前端請求&#xff08;不包含&#xff09;訪問后端服務接口&#xff0c;接口通過檢索知識庫&#xff0c;封裝提示詞&#xff0c;調用deepseek的&#xff0c;并返回給前端的全過程&#xff0c;非完整代碼&#xff0c;不可直接運行。 1.基于servlet封裝異步請求 為…

歸并排序的思路與實現

歸并排序主要是兩大模塊 分治 和 合并 即將已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每個子序列有序&#xff0c;再使子序列段間有序。若將兩個有序表合并成一個有序表&#xff0c;稱為二路歸并 由于使用了新的數組 那么空間復雜度就為O(n) 但這…

Word中公式自動標號帶章節編號

&#xff08;1&#xff09;插入一行三列的表格&#xff0c;設置寬度分別為0.5&#xff0c;13.39和1.5&#xff0c;設置縱向居中&#xff0c;中間列居中對齊&#xff0c;最右側列靠右對齊&#xff0c;設置段落如下 &#xff08;2&#xff09;插入域代碼 【Word】利用域代碼快速實…

阿里云服務器環境部署 四 MySQL主從配置

安裝MySQL 導入mysql鏡像 docker load -i /opt/dockerinstall/mysql/mysql-8.1.0.tar docker run --privilegedtrue --name mysql8 --restartunless-stopped -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -v /usr/local/mysql/logs:/var/log/mysql -v /usr/local/mysql/d…

[RH342]iscsi配置與排錯

[RH342]iscsi配置與排錯 1. 服務端配置1.1 安裝targetcli1.2 準備磁盤1.3 服務端配置1.4 防火墻配置 2. 客戶端配置2.1 安裝客戶端軟件2.2 配置客戶端2.3 連接登錄服務端2.4 掛載使用 3. 安全驗證擴展3.1 服務端3.2 客戶端 4. 常見的排錯點4.1 服務端常見錯誤4.2 客戶端常見錯誤…

服裝零售行業數字化時代的業務與IT轉型規劃P111(111頁PPT)(文末有下載方式)

服裝零售行業數字化時代的業務與IT轉型規劃P111 詳細資料請看本解讀文章的最后內容。 隨著數字化技術的迅猛發展&#xff0c;服裝零售行業正經歷著前所未有的變革。本文將對《服裝零售行業數字化時代的業務與IT轉型規劃P111》進行詳細解讀&#xff0c;探討未來幾年內該行業的…

基于javaweb的SSM+Maven寵物領養寵物商城流浪動物管理系統與實現(源碼+文檔+部署講解)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論…

PostgreSQL 數據庫中導入大量數據

在 PostgreSQL 數據庫中導入大量數據,可根據數據來源和格式選擇不同的方法。以下為你詳細介紹幾種常見的方式: 1. 使用 COPY 命令(適用于本地數據文件) COPY 命令是 PostgreSQL 內置的高效數據導入工具,適合處理本地的數據文件。 步驟 準備數據文件 確保你的數據文件格…

C++語法之命名空間二

A.h頭文件中代碼&#xff1a; namespace a {void 輸出(); }; A.cpp源文件中代碼&#xff1a; #include <iostream> #include "A.h" void a::輸出() {std::cout << "A.h里的輸出函數" << std::endl; } B.h頭文件中代碼&#xff1a; …

基于FPGA的DDS連續FFT 仿真驗證

基于FPGA的 DDS連續FFT 仿真驗證 1 摘要 本文聚焦 AMD LogiCORE IP Fast Fourier Transform (FFT) 核心,深入剖析其在 FPGA 設計中的應用。該 FFT 核心基于 Cooley - Tukey 算法,具備豐富特性,如支持多種數據精度、算術類型及靈活的運行時配置。文中詳細介紹了其架構選項、…

美團Leaf分布式ID生成器使用教程:號段模式與Snowflake模式詳解

引言 在分布式系統中&#xff0c;生成全局唯一ID是核心需求之一。美團開源的Leaf提供了兩種分布式ID生成方案&#xff1a;號段模式&#xff08;高可用、依賴數據庫&#xff09;和Snowflake模式&#xff08;高性能、去中心化&#xff09;。本文將手把手教你如何配置和使用這兩種…

Swift 并發任務的協作式取消

在 Swift 并發&#xff08;Swift Concurrency&#xff09;中&#xff0c;任務&#xff08;Task&#xff09;不會被強行終止&#xff0c;而是采用**協作式取消&#xff08;cooperative cancellation&#xff09;**機制。這意味著任務會被標記為“已取消”&#xff0c;但是否真正…

大數據(1.1)紐約出租車大數據分析實戰:從Hadoop到Azkaban的全鏈路解析與優化

目錄 一、背景與數據價值? ?二、技術選型與組件分工? ?三、數據準備與預處理? 四、實戰步驟詳解? ?1. 數據上傳至HDFS ?2. Hive數據建模與清洗? 4?.2.1 建表語句&#xff08;分區表按年份&#xff09;?&#xff1a; ?4?.2.2 數據清洗&#xff08;剔除無效…

代碼隨想錄刷題day50|(回溯算法篇)131.分割回文串▲

目錄 一、回溯算法基礎知識 二、分割回文串思路 2.1 如何切割 2.2 判斷回文 2.3 回溯三部曲 2.4 其他問題 三、相關算法題目 四、總結 一、回溯算法基礎知識 詳見&#xff1a;代碼隨想錄刷題day46|&#xff08;回溯算法篇&#xff09;77.組合-CSDN博客 二、分割回文…

VS Code PowerShell、Windows PowerShell、CMD 的區別與聯系

VS Code PowerShell、Windows PowerShell、CMD 的區別與聯系? VS Code PowerShell、Windows PowerShell、CMD 的區別與聯系&#xff1a; 一、核心概念對比 名稱 全稱 類型 定位 VS Code PowerShell Visual Studio Code PowerShell 代碼編輯器集成終端 開發/腳本編寫…

關于Unity的CanvasRenderer報錯

MissingReferenceException: The object of type ‘CanvasRenderer’ has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. UnityEngine.UI.GraphicRaycaster.Raycast (UnityEng…

C++編譯流程

編譯器其實就是一個翻譯器&#xff0c;把我們的文件內容翻譯成機器能夠看懂的指令&#xff0c;但如何合理翻譯是核心。 C語言編譯 需要經過以下幾步&#xff1a; 詞法分析&#xff1a;掃描代碼&#xff0c;確定單詞類型&#xff0c;比如是變量還是函數&#xff0c;是標識符還…