繁体   English   中英

使用 xml.etree 保留命名空间

[英]preserve namespaces with xml.etree

在源文件的根元素中定义命名空间时, lxml会在 output 中复制所有命名空间。 我需要用xml.etree来做到这一点。 更好的是只使用 output 那些使用过的,但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 强制为 output “未使用”命名空间,但命名空间来自源文件,因此 ZA7F5F35426B9274117FC9231B562Z 代码不知道它们。

首先,在不添加缺少的命名空间的情况下生成 output。 获取从该 output 中找到的命名空间。 然后,通过添加未找到的命名空间来生成最终的 output。

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>

欢迎使用不需要生成 output 两次的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM