python - 使用 xml.etree 保留命名空间
问题描述
在源文件的根元素中定义名称空间时,lxml
在输出中重现所有名称空间。我需要用xml.etree
. 更好的是只输出那些使用过的,但xml.etree
没有找到所有的。
一种解决方案是使用root.set()
. 但是,这xml.etree
会复制找到的任何命名空间,如下所示。
适合在命令提示符下粘贴的完整示例:
import xml.etree.ElementTree as ET
try:
from io import StringIO
except ImportError:
from StringIO import StringIO
def get_namespaces(sourcestring):
sourcefile = StringIO(sourcestring)
return dict(
[node for _, node in ET.iterparse(sourcefile, events=['start-ns'])])
ET._namespace_map = dict() # remove any previously registered namespaces
sourcetext = (
'<desc xmlns="uri_a" xmlns:b="uri_b" xmlns:c="uri_c"'
' b:foo="c:bar">a</desc>')
source = ET.fromstring(sourcetext)
namespaces = get_namespaces(sourcetext)
for prefix, uri in namespaces.items():
ET.register_namespace(prefix, uri)
if prefix:
tag = 'xmlns:' + prefix
else:
tag = 'xmlns'
source.set(tag, uri)
print(ET.tostring(source, encoding='unicode'))
结果,导致我的应用程序失败:
<desc xmlns="uri_a" xmlns:b="uri_b" xmlns="uri_a" xmlns:b="uri_b" xmlns:c="uri_c" b:foo="c:bar">a</desc>
这类似于强制 xml.etree 输出“未使用”命名空间,但命名空间来自源文件,因此 Python 代码不知道它们。
解决方案
首先,在不添加缺少的命名空间的情况下生成输出。获取从该输出中找到的命名空间。然后,通过添加未找到的命名空间来生成最终输出。
def add_namespaces_not_found(root):
result_with_namespaces_found = ET.tostring(root, encoding='unicode')
namespaces_found = get_namespaces(result_with_namespaces_found)
for prefix, uri in namespaces.items():
if prefix not in namespaces_found:
if prefix:
tag = 'xmlns:' + prefix
else:
tag = 'xmlns'
root.set(tag, uri)
结果:
<desc xmlns="uri_a" xmlns:b="uri_b" xmlns:c="uri_c" b:foo="c:bar">a</desc>
欢迎不需要生成两次输出的解决方案。
推荐阅读
- ipaf - 我们如何从 IDE 获取 ALM 文件夹 ID?
- ruby-on-rails - Xero Ruby SDK for OAuth 2.0 在tenantId 中发送请求
- mongodb - 用于 postgres 的 Mongodb FDW 扩展
- undefined - 架构 armv7 的未定义符号(Mopub 谷歌网络)
- c++ - doxygen/sphinx C++17中的`unsigned int constexpr`
- c# - 锁定局部变量时出错:“可能不正确地分配给 local 这是 using 或 lock 语句的参数。”
- java - HPFortify - 动态代码评估:不安全的反序列化
- powershell - Powershell:使用格式化日期重命名文件夹
- datetime - 检索日期格式错误的数据 - 雪花
- python - 如何在 Python 中通过 __init__ 设置类变量?