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.mzph.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;是标识符还…