【问题标题】:Find the namespaces from xml with python ElementTree with redeclared namespaces使用带有重新声明命名空间的 python ElementTree 从 xml 中查找命名空间
【发布时间】:2018-10-24 00:03:22
【问题描述】:

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

<site:Stack xmlns:site='http://stackoverflow.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 反序列化为自定义类对象,然后(经过一些处理/编辑)重新序列化为格式良好的 XML 文件。

即来自 Oracle 的 XML 示例。 请注意 Orders 如何更改为 Confirm,但前缀相同。

<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'])
])

【问题讨论】:

  • 据我所知,对两个不同的命名空间 URI 使用相同的前缀是合法的。见stackoverflow.com/q/41774652/407651
  • 从那个答案看来,Oracle 给出的上述 XML 实际上是无效的。您链接的答案表明 NameSpace 允许相同,但最终 Xpath Mapping 必须是唯一的。所以在我的例子中,PO 不能同时映射到 Order 和 Confirmation。
  • 我不认为您的 XML 示例是“无效的”。我已经使用 Python 的 ElementTree 模块以及 xmllint 对其进行了解析,并且没有错误。
  • 我知道它的“有效”但格式正确是另一个我不确定的问题。就像我在原始帖子中提到的那样, register_namespace 不起作用。我已将其作为 ET 读入,将其分解,然后重新序列化回 ET。然而就像我之前说的,标准库函数调用不能使用它,因为有两个重复的前缀 PO。即使在您链接到我的答案中,答案也明确提到每个映射都必须是唯一的。
  • 文档格式正确。如果不是,解析器会抛出错误。我想说的是,对于两个不同的命名空间使用相同的前缀是不寻常的(并且令人困惑),但它不会违反 XML 文档的任何规则。

标签: python xml elementtree


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2017-07-08
    • 2023-04-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2023-03-17
    相关资源
    最近更新 更多