使用具有重新声明的命名空间的 python ElementTree 从 xml 中查找命名空间

Find the namespaces from xml with python ElementTree with redeclared namespaces

如果命名空间定义被重新声明,如何获得正确的命名空间?细说:前缀相同,但属性值不同,因此重新声明。

<site:Stack xmlns:site='http://whosebug.com'><site:Stack xmlns:site='https://math.stackexchange.com/'>

根据我在 Microsoft 的 XML 文档中阅读的内容,这是可以接受的,它只是 重新声明命名空间 除非这是不被接受的形式,那么我可以关闭这个问题。

这是一个问题,因为它扰乱了大多数获取命名空间的字典方法,但它也扰乱了标准库中的 ElementTree.register_namespace(prefix, uri) 方法。 Register_namespace 非常重要,因为它用于解析命名空间标签,因为 ET 解析以 clark 表示法给出标签,例如 Header 元素,如下所示 <{http://schemas.xmlsoap.org/soap/envelope/}:Header/> 使用 register_namespace 将上面的内容解析回 <SOAP-ENV:Header/>。 这给我带来了严重的问题,因为我将 XML 反序列化为自定义 class 对象,然后重新序列化(经过一些 processing/edits)为格式正确的 XML 文件。

即来自 Oracle 的 XML 示例。 请注意订单如何更改为确认,但前缀相同。

<PO:order xmlns:PO="http://gizmos.com/orders/"> 更改为 <PO:confirmation xmlns:PO="http://gizmos.com/confirm">

<?xml version="1.0" encoding="utf-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
    <SOAP-ENV:Fault>
        <faultcode>SOAP-ENV:Client</faultcode>
        <faultstring>Message does not have necessary info</faultstring>
        <faultactor>http://gizmos.com/order</faultactor>
            <detail>
                <PO:order xmlns:PO="http://gizmos.com/orders/">
                Quantity element does not have a value
                </PO:order>
                <PO:confirmation xmlns:PO="http://gizmos.com/confirm">
                Incomplete address: no zip code
                </PO:confirmation>
            </detail>
    </SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

注意:我知道您可以使用以下方法获取带有命名空间的字典。但这将使用任何命名空间的最新声明。同样,ET.register_namespace 会做同样的事情,这是最近使用的声明。

import xml.etree.ElementTree as ET
my_namespaces = dict([
    node for (_, node) in ET.iterparse('file.xml', events=['start-ns'])
])

此 XML 格式正确且有效。在您仅使用标准库中的 ElementTree 的情况下,ElementTree.register_namespace(prefix, uri) 不能用于解析名称空间,因为您作为参数输入的字典将不起作用,因为您将具有具有不同 URI 的重复前缀, 这对于 python 字典也是无效的。

如果使用 xpath,则有一个解决方案,它使用到前缀的唯一映射。所以以oraclexml为例。 P1 maps to PO to http://gizmos.com/orders/,以及 P2 maps to PO to http://gizmos.com/confirm/

如果不编辑原始 XML 并且仅使用 ElementTree,则必须手动解决此问题。