Python使用ElementTree解析XML时遇到带前缀标签被展开问题
问题解答
1. 该行为是正常预期吗
是,这是Python标准库xml.etree.ElementTree处理XML命名空间的标准设计。XML中ops这类前缀只是命名空间URI的临时别名,真正唯一标识命名空间的是http://www.si2.org/schemas/OPS这类完整URI,ET在解析时会自动将标签转换为「{命名空间URI}本地标签名」的通用格式,避免不同XML文件中相同前缀对应不同命名空间的冲突问题。
2. 简化命名空间查询的推荐方案
不需要手动拼接带URI的标签名,findall/find/iterfind等方法都支持传入自定义命名空间映射字典,你可以自己指定查询时用的前缀,和XML里的前缀对应上即可,示例代码如下:
from xml.etree import ElementTree as ET # 定义命名空间映射,key是你查询时想用的前缀,value是对应命名空间URI ns = { "ops": "http://www.si2.org/schemas/OPS" } tree = ET.parse(OPSDRMFile) root = tree.getroot() # 查询时直接用前缀写法,第二个参数传入命名空间字典即可 # 比如找所有ops:RulesSection元素 rules_sections = root.findall("ops:RulesSection", ns) # 找ops:RulesSection下的ops:NewTagToFind元素 new_tags = root.findall("ops:RulesSection/ops:NewTagToFind", ns)
这种写法和你预期的ops:前缀用法完全一致,不需要修改查询逻辑,也不用手动拼接长串的URI格式标签。
3. 完全关闭命名空间展开的方案
如果确定你的XML中没有同本地名、不同命名空间的元素/属性,也可以选择在解析后手动去掉所有标签的命名空间前缀,示例实现如下:
def strip_namespace(root): for elem in root.iter(): # 去掉标签中的{uri}部分,只保留本地名 if '}' in elem.tag: elem.tag = elem.tag.split('}', 1)[1] # 同时处理属性的命名空间(如果需要) attrs = list(elem.attrib.keys()) for attr in attrs: if '}' in attr: val = elem.attrib.pop(attr) elem.attrib[attr.split('}', 1)[1]] = val return root # 解析后调用该函数即可 tree = ET.parse(OPSDRMFile) root = strip_namespace(tree.getroot()) # 之后直接用本地名查询即可,不需要带前缀和命名空间 print(root.findall("RulesSection"))
⚠️ 该方案存在匹配冲突风险,非必要场景更推荐使用命名空间字典的方案。
内容的提问来源于stack exchange,提问作者user15290844
相关产品推荐
相关产品推荐

