在 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()
的问题在于:
-
你需要知道
prefix
和URI
不能与默认命名空间一起使用。
例如如果 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 是的,如果您想对此进行更多控制,我认为您可以将XMLPullParser
与start-ns
事件一起使用,获取命名空间然后调用ET.register_namespace
。
感谢您的回答。在对 XML 进行简单的调整后,我的命名空间被替换了。以上是关于在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间的主要内容,如果未能解决你的问题,请参考以下文章