如何获取命名空间的元素的属性

UpA*_*dam 6 python xml lxml xml-parsing

我正在解析每天从供应商处收到的XML文档,它大量使用名称空间。我已将问题最小化为一个最小子集:

我需要解析一些元素,所有元素都是具有特定属性的元素的子元素。
我可以用来lxml.etree.Element.findall(TAG, root.nsmap)查找我需要检查其属性的候选节点。

然后,我试图Elements通过我知道它使用的名称来检查每个属性:这里具体是ss:Name。如果该属性的值是所需的值,那么我将更深入地研究说Element(继续做其他事情)。

我怎样才能做到这一点?

我正在解析的XML大致

<FOO xmlns="SOME_REALLY_LONG_STRING"
 some gorp declaring a bunch of namespaces one of which is 
 xmlns:ss="THE_VERY_SAME_REALLY_LONG_STRING_AS_ROOT"
>
    <child_of_foo>
        ....
    </child_of_foo>
    ...
    <SomethingIWant ss:Name="bar" OTHER_ATTRIBS_I_DONT_CARE_ABOUT>
        ....
        <MoreThingsToLookAtLater>
            ....
        </MoreThingsToLookAtLater>
        ....
    </SomethingIWant>
    ...
</FOO>
Run Code Online (Sandbox Code Playgroud)

我找到了我想要的第一个元素SomethingIWant(最终我想要它们,所以我确实找到了所有元素)

import lxml
from lxml import etree

tree = etree.parse(myfilename)
root = tree.getroot()
# i want just the first one for now
my_sheet = root.findall('ss:RecordSet', root.nsmap)[0]
Run Code Online (Sandbox Code Playgroud)

现在,我想ss:Name从该元素中获取属性,以进行检查,但不确定如何?

我知道这my_sheet.attrib将向我显示原始URI,然后显示属性名称,但我不希望这样。我需要检查它是否具有用于特定命名空间属性的特定值。(由于错误,我可以完全跳过此元素)。

我尝试使用,lxml.etree.ElementTree.attrib.get()但似乎没有获得任何有用的信息。

有任何想法吗?

har*_*r07 6

lxml超过标准的 python XML 解析器的优点之一是lxml通过xpath()方法完全支持 XPath 1.0 规范。所以我xpath()大部分时间都会使用方法。您当前案例的工作示例:

from lxml import etree

xml = """<FOO xmlns="SOME_REALLY_LONG_STRING"
 xmlns:ss="THE_VERY_SAME_REALLY_LONG_STRING_AS_ROOT"
>
    <child_of_foo>
        ....
    </child_of_foo>
    ...
    <SomethingIWant ss:Name="bar">
        ....
    </SomethingIWant>
    ...
</FOO>"""

root = etree.fromstring(xml)
ns = {'ss': 'THE_VERY_SAME_REALLY_LONG_STRING_AS_ROOT'}

# i want just the first one for now
result = root.xpath('//@ss:Name', namespaces=ns)[0]
print(result)
Run Code Online (Sandbox Code Playgroud)

输出 :

bar
Run Code Online (Sandbox Code Playgroud)

更新 :

演示如何从 current 获取命名空间中的属性的修改示例element

ns = {'ss': 'THE_VERY_SAME_REALLY_LONG_STRING_AS_ROOT', 'd': 'SOME_REALLY_LONG_STRING'}

element = root.xpath('//d:SomethingIWant', namespaces=ns)[0]
print(etree.tostring(element))

attribute = element.xpath('@ss:Name', namespaces=ns)[0]
print(attribute)
Run Code Online (Sandbox Code Playgroud)

输出 :

<SomethingIWant xmlns="SOME_REALLY_LONG_STRING" xmlns:ss="THE_VERY_SAME_REALLY_LONG_STRING_AS_ROOT" ss:Name="bar">
        ....
    </SomethingIWant>
    ...

bar
Run Code Online (Sandbox Code Playgroud)


UpA*_*dam 5

我很确定这是一种非常糟糕的非 PYTHONIC 非理想方式;似乎必须有更好的方法……但我发现我可以这样做:

SS_REAL = "{%s}" % root.nsmap.get('ss')

然后我可以这样做: my_sheet.get( SS_REAL + "NAME" )

它让我得到了我想要的......但这不可能是做到这一点的正确方法......