Python ElementTree的iter()/find()/findall()无法匹配XML标签问题
问题原因
你遇到的匹配失败、标签带前缀的问题,本质是XML命名空间导致的:
- 你XML根节点中声明的
xmlns="http://cpe.mitre.org/dictionary/2.0"是默认命名空间,所有没有显式加自定义前缀的标签(比如cpe-list、cpe-item、title等)都归属于该命名空间 - ElementTree处理带命名空间的标签时,会将标签存储为
{命名空间URI}标签名的格式(也叫Clark notation),你直接传入不带命名空间的cpe-item匹配,和实际存储的标签值完全不一致,自然返回空结果
解决方案
有两种常用的匹配方式可选:
方案1:使用命名空间映射(推荐)
先定义命名空间和自定义前缀的映射字典,匹配时用前缀:标签名的格式即可,可读性更好:
import xml.etree.ElementTree as ET # 读取XML部分和你原有逻辑一致,补充encoding避免乱码 infile = open(filename, "r", encoding="utf-8") xml = infile.read() infile.close() parser = ET.XMLParser(encoding="utf-8") root = ET.fromstring(xml, parser=parser) # 定义命名空间映射,key可自定义,value必须和XML中声明的URI完全一致 ns = { "cpe": "http://cpe.mitre.org/dictionary/2.0", "cpe23": "http://scap.nist.gov/schema/cpe-extension/2.3" } # 查找所有cpe-item节点 for item in root.iter("cpe:cpe-item", namespaces=ns): # 读取cpe-item的name属性 print(item.get("name")) # 查找子节点title的文本,同样要带命名空间前缀 title = item.find("cpe:title", namespaces=ns).text print(title) # 查找带自定义前缀的cpe23-item节点 cpe23_name = item.find("cpe23:cpe23-item", namespaces=ns).get("name") print(cpe23_name)
方案2:直接写完整标签名
如果不想定义映射字典,也可以直接传入完整的{命名空间URI}标签名格式的字符串匹配:
# 直接匹配cpe-item for item in root.iter("{http://cpe.mitre.org/dictionary/2.0}cpe-item"): print(item.get("name")) # 匹配title子节点 title = item.find("{http://cpe.mitre.org/dictionary/2.0}title").text print(title)
内容的提问来源于stack exchange,提问作者I'm Root James
相关产品推荐
相关产品推荐

