在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间
How to preserve namespaces when parsing xml via ElementTree in Python
假设我有以下 XML,我想使用 Python 的 ElementTree
进行修改:
<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
解决这个问题吗?
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,我想使用 Python 的 ElementTree
进行修改:
<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
解决这个问题吗?
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')