Python处理带命名空间XML需显式声明命名空间映射字典,XPath中用“前缀:标签”形式查找,如ns:channel;默认命名空间也须指定前缀,URI必须完全匹配,不支持*通配符跨空间匹配。
Python处理带命名空间的XML,关键在于正确声明和使用命名空间前缀,否则find、findall等方法会找不到元素。
ElementTree默认不自动识别XML文档中的xmlns声明。即使XML里写了xmlns="http://example.com/ns",你也不能直接用root.find("item")——必须显式传入命名空间映射字典。
prefix:tagname写法,如"ns:item"
xmlns="...")也要给它起个前缀,不能留空namespaces参数进行查找这是最常用也最推荐的方式:构造命名空
间字典,传给find、findall、iterfind等方法。
例如有如下XML:
立即学习“Python免费学习笔记(深入)”;
My Feed Post 1
对应代码为:
import xml.etree.ElementTree as ETtree = ET.parse("feed.xml") root = tree.getroot()
声明命名空间:这里用"ns"作为前缀
ns = {"ns": "https://www./link/ff4776b449efb88b35fbf6187af9771e"}
正确查找
channel = root.find("ns:channel", namespaces=ns) title = channel.find("ns:title", namespaces=ns) items = channel.findall("ns:item", namespaces=ns)
如果XML中用了多个带前缀的命名空间(如xmlns:dc="http://purl.org/dc/elements/1.1/"),只需在字典中一并声明:
ns = {
"rss": "https://www./link/ff4776b449efb88b35fbf6187af9771e",
"dc": "http://purl.org/dc/elements/1.1/"
}
查找 dc:creator
creator = item.find("dc:creator", namespaces=ns)
注意:前缀名(如"dc")可以任意取,只要和XPath中一致即可;URI必须完全匹配XML中声明的值(包括末尾斜杠)。
ElementTree不支持*通配符跨命名空间匹配。不要写root.findall("*:item")——它不会生效。
root.tag打印根元素全名,如{https://www./link/ff4776b449efb88b35fbf6187af9771e}rss,从中提取URIelem.tag.split("}")[-1],再遍历比对,但性能较差,仅作备用lxml支持etree.XPath和更灵活的命名空间处理,适合复杂场景