Python ElementTree默认命名空间?

27

在 Python ElementTree 中有定义默认/无前缀命名空间的方法吗?似乎这种方法不起作用...

ns = {"":"http://maven.apache.org/POM/4.0.0"}
pom = xml.etree.ElementTree.parse("pom.xml")
print(pom.findall("version", ns))

也不是这样的:

ns = {None:"http://maven.apache.org/POM/4.0.0"}
pom = xml.etree.ElementTree.parse("pom.xml")
print(pom.findall("version", ns))

这样做的话,我必须给每个元素添加前缀:

ns = {"mvn":"http://maven.apache.org/POM/4.0.0"}
pom = xml.etree.ElementTree.parse("pom.xml")
print(pom.findall("mvn:version", ns))
在OSX上使用Python 3.5。
编辑:如果答案是否定的,你仍然可以获得奖励 :-)。我只是想从一个长期使用它的人那里得到一个明确的“否”回答。

使用 ElementTree,你必须使用前缀。如果你使用 lxml,你可以使用 .nsmap 代替硬编码的前缀。详情请参见 https://dev59.com/vmUq5IYBdhLWcg3wBL7j。 - gtlambert
3个回答

29

注意:对于Python 3.8+,请参见此答案


没有直接的方法可以透明地处理默认命名空间。将空命名空间分配一个非空名称是常见的解决方案,就像您已经提到的那样:

ns = {"mvn":"http://maven.apache.org/POM/4.0.0"}
pom = xml.etree.ElementTree.parse("pom.xml")
print(pom.findall("mvn:version", ns))

请注意,lxml.etree不允许显式使用空命名空间。否则你会得到以下错误:

ValueError: empty namespace prefix is not supported in ElementPath


但是,您可以在加载XML输入数据时通过删除默认命名空间定义来简化操作:

import xml.etree.ElementTree as ET
import re
 
with open("pom.xml") as f:
    xmlstring = f.read()
 
# Remove the default namespace definition (xmlns="http://some/namespace")
xmlstring = re.sub(r'\sxmlns="[^"]+"', '', xmlstring, count=1)
 
pom = ET.fromstring(xmlstring) 
print(pom.findall("version"))

处理单引号:r"""\s(xmlns="[^"]+"|\sxmlns='[^']+')""" - juloo65
1
为了修复@juloo65的答案: xmlstring = re.sub(r"""\s(xmlns="[^"]+"|xmlns='[^']+')""", '', xmlstring, count=1) - Dariosky
注意:在使用html5lib将HTML序列化HTML转换为XHTML时,“在加载XML输入数据时删除默认命名空间定义”不适用。 - Damian Yerrick
自 Python 3.8+ 起,这不再是被接受的答案。请参阅 https://dev59.com/mlsX5IYBdhLWcg3wS9w7#62398604。 - delocalizer
1
@delocalizer 谢谢,已经在答案顶部添加了链接。 - alecxe

13

3

您可以使用以下代码获取默认命名空间:

namespace = pom.getroot().tag.split("}")[0]+"}"

然后,当您搜索元素时,将其添加到搜索路径中:
print(pom.findall(namespace+"version"))

不是一个优雅的解决方案,但它起作用了。

这不是给你根元素的命名空间吗?这可能与默认命名空间相同,也可能不同。 - J. Beattie
@J.Beattie 你可能是正确的;我可能没有使用正确的术语。 - Peppe L-G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接