【问题标题】:Python ElementTree default namespace?Python ElementTree 默认命名空间?
【发布时间】:2020-12-26 13:43:15
【问题描述】:

有没有办法在 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。

编辑:如果答案是“否”,您仍然可以获得赏金 :-)。我只是想从一个花了很多时间使用它的人那里得到一个明确的“不”。

【问题讨论】:

标签: python xml python-3.x namespaces elementtree


【解决方案1】:

注意:对于 Python 3.8+,请参阅 this answer


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

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: ElementPath 不支持空的命名空间前缀


不过,您可以在加载 XML 输入数据时通过 removing the default namespace definition 让事情变得更简单:

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 答案:xmlstring = re.sub(r"""\s(xmlns="[^"]+"|xmlns='[^']+')""", '', xmlstring, count=1)
  • 注:“在加载 XML 输入数据时删除默认命名空间定义”不适用于使用 html5lib 将 HTML 序列化 HTML 转换为 XHTML。
  • 这应该不再是 Python 3.8+ 的公认答案。见stackoverflow.com/a/62398604/6705037
  • @delocalizer 谢谢,在答案顶部添加了一个链接。
【解决方案2】:

Python 3.8 中的ElementTree 允许空字符串作为前缀,所以你可以声明:

ns = {'': 'http://maven.apache.org/POM/4.0.0'}

并将其用作find* 方法中的第二个参数。

来源:https://docs.python.org/3.8/library/xml.etree.elementtree.html?highlight=xml#xml.etree.ElementTree.Element.find

【讨论】:

    【解决方案3】:

    您可以使用以下命令检索默认命名空间:

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

    然后,当您搜索元素时,将其添加到您的搜索路径中:

    print(pom.findall(namespace+"version"))
    

    不是一个优雅的解决方案,但它确实有效。

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多