XML - 不带命名空间的查找

XML - Find without namespace

提问人:Альберт Александров 提问时间:9/5/2023 最后编辑:mzjnАльберт Александров 更新时间:9/6/2023 访问量:89

问:

下面有 xml:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:mt_queryRequest xmlns:ns0="http://x5.ru/mdm/common">
    <messageHeader>
        <reqId>6437636</reqId>
        <targetSystem>GGG</targetSystem>
        <serviceInterface>NS</serviceInterface>
        <interfaceNamespace/>
    </messageHeader>
    <Item xmlns="http://www.ibm.com/mdm/entry01">
        <MDM_ID xmlns="">897346</MDM_ID>
        <NAME xmlns="">
            <ru_RU is_delta="True" xmlns="http://www.ibm.com/mdm/entry01">NANANN</ru_RU>
        </NAME>
        <SAPNAME xmlns="">
            <ru_RU xmlns="http://www.ibm.com/mdm/entry01">NANANN</ru_RU>
        </SAPNAME>
        <FULLNAME xmlns="">
            <ru_RU xmlns="http://www.ibm.com/mdm/entry01">NANANN</ru_RU>
        </FULLNAME>
        <IS_RESIDENT xmlns="">Yes</IS_RESIDENT>
        <INN xmlns="">549348892</INN>
        <KPP xmlns="">693628032</KPP>
        <CONTRAGENT_FORM xmlns="">UL</CONTRAGENT_FORM>
        <CONTRAGENT_GROUP occ="6543234" xmlns="">
            <GROUP xmlns="http://www.ibm.com/mdm/entry01">Sub (Z013)</GROUP>
            <SAPCODE xmlns="http://www.ibm.com/mdm/entry01">8012312</SAPCODE>
            <IS_ARCHIVE xmlns="http://www.ibm.com/mdm/entry01">No</IS_ARCHIVE>
            <GROUP_ID xmlns="http://www.ibm.com/mdm/entry01">P013</GROUP_ID>
            <IS_ARCHIVE_ID xmlns="http://www.ibm.com/mdm/entry01">0</IS_ARCHIVE_ID>
        </CONTRAGENT_GROUP>
        <NAMES_HISTORY occ="1715174529" xmlns="">
            <SAPNAME xmlns="http://www.ibm.com/mdm/entry01">
                <ru_RU xmlns="">Ghcsjdhc</ru_RU>
            </SAPNAME>
        </NAMES_HISTORY>
        <NORMALIZATION_STATUS xmlns="">Normalized</NORMALIZATION_STATUS>
        <CONTRAGENT_FORM_ID xmlns="">3</CONTRAGENT_FORM_ID>
        <IS_RESIDENT_ID xmlns="">1</IS_RESIDENT_ID>
    </Item>
</ns0:mt_queryRequest>

我不得不在路径中使用命名空间:

import xml.etree.ElementTree as ET

xml = ET.fromstring(xml_string)
res = xml.find('.//{http://www.ibm.com/mdm/entry01}Item/CONTRAGENT_GROUP/{http://www.ibm.com/mdm/entry01}GROUP')')

如您所见,路径中的命名空间是硬编码的,我担心命名空间可能会更改,或者会有多个命名空间(不知何故,我不知道)。

是否有可能摆脱命名空间?我发现的唯一方法是通过 xmltodict lib 将 xml 转换为 dict 并使用 dict。

python elementtree xml命名空间

评论

1赞 mzjn 9/6/2023
可以使用命名空间通配符:stackoverflow.com/a/61154644/407651
1赞 Hermann12 9/6/2023
缺少 xml 的根元素,因此您会看到 ns0: 前缀。也许您可以将根添加到您的 xml 示例中。

答:

1赞 Hermann12 9/6/2023 #1

您可以像以下网站一样进行搜索:

res = root.find('.//{*}GROUP')
print(res.text)

输出:

Sub (Z013)
1赞 LMC 9/6/2023 #2

使用 XPath 功能,xpath 函数将有助于查找元素,而不管其命名空间如何lxmllocal-name()

>>> from lxml import etree
>>> doc = etree.parse("tmp.xml")
>>> grp = doc.xpath('.//*[local-name()="Item"]/CONTRAGENT_GROUP/*[local-name()="GROUP"]')
>>> print(grp[0].text)
Sub (Z013)
2赞 Michael Kay 9/6/2023 #3

原则上,如果命名空间发生变化,那么所有的赌注都会关闭,因为当命名空间发生变化时,其他一切都可能发生变化。只有命名空间才能告诉您这是哪种类型的 XML 文档。

您似乎正在使用(并且被建议使用)XPath 1.0 的一些非标准扩展。在 XPath 2.0 中,可以使用以下语法按命名空间 URI 和本地名称查找元素

//Q{http://www.ibm.com/mdm/entry01}Item

并且仅通过本地名称和语法

//*:Item

但我认为 ElementTree 不支持这些。