在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间

Posted

技术标签:

【中文标题】在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间【英文标题】:How to preserve namespaces when parsing xml via ElementTree in Python 【发布时间】:2019-06-23 15:48:04 【问题描述】:

假设我有以下想要使用 Python 的 ElementTree 修改的 XML:

<root xmlns:prefix="URI">
  <child company:name="***"/>
  ...
</root> 

我正在对 XML 文件进行一些修改,如下所示:

import xml.etree.ElementTree as ET
tree = ET.parse('filename.xml')
# XML modification here
# save the modifications
tree.write('filename.xml')

那么 XML 文件看起来像:

<root xmlns:ns0="URI">
  <child ns0:name="***"/>
  ...
</root>

如您所见,名称空间prefix 更改为ns0。我知道使用ET.register_namespace() 提到的here。

ET.register_namespace() 的问题在于:

    你需要知道prefixURI 不能与默认命名空间一起使用。

例如如果 xml 看起来像:

<root xmlns="http://uri">
    <child name="name">
    ...
    </child>
</root>

它将被转换为:

<ns0:root xmlns:ns0="http://uri">
    <ns0:child name="name">
    ...
    </ns0:child>
</ns0:root>

如您所见,默认命名空间更改为ns0

ElementTree有没有办法解决这个问题?

【问题讨论】:

xml.etree.ElementTree - Trouble setting xmlns = '...'的可能重复 dup 链接明确使用ET.register_namespace(...。 Edit你的问题minimal reproducible example展示你如何使用它。 @stovfl 这不是关于保留命名空间,也没有帮助我。命名空间不应该是硬编码的,它可以是xmlns:prefix="URI",带有任何前缀和URI。 使用 ElementTree 保留命名空间前缀的唯一方法是使用 register_namespace()。如果您不喜欢这样,请尝试使用 lxml。 查看***.com/a/42372404/407651 获取文档中命名空间的方法。 【参考方案1】:

ElementTree 将替换那些未使用ET.register_namespace 注册的命名空间前缀。要保留命名空间前缀,您需要先注册它,然后再将修改写入文件。以下方法完成这项工作并在全局范围内注册所有命名空间,

def register_all_namespaces(filename):
    namespaces = dict([node for _, node in ET.iterparse(filename, events=['start-ns'])])
    for ns in namespaces:
        ET.register_namespace(ns, namespaces[ns])

这个方法应该在ET.parse方法之前调用,这样命名空间将保持不变,

import xml.etree.ElementTree as ET
register_all_namespaces('filename.xml')
tree = ET.parse('filename.xml')
# XML modification here
# save the modifications
tree.write('filename.xml')

【讨论】:

这个解决方案比我在同一主题的许多其他问题上看到的要好得多。感谢分享。 这是否意味着xml需要被解析两次?或者我可以像我这样做的那样以某种方式让 ElementTree 脱离这个过程吗? @Starwarswii 是的,如果您想对此进行更多控制,我认为您可以将XMLPullParserstart-ns 事件一起使用,获取命名空间然后调用ET.register_namespace 感谢您的回答。在对 XML 进行简单的调整后,我的命名空间被替换了。

以上是关于在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间的主要内容,如果未能解决你的问题,请参考以下文章

Python:XPath 在 ElementTree 中不可用

为啥在python中通过字符串声明unicode?

python 在python中通过线性回归分析文本

python 在python中通过套接字接收消息

python 在python中通过套接字发送消息

python-23 xml.etree.ElementTree模块