在 lxml 中查找具有未知命名空间的元素

Tri*_*ran 3 python xml lxml

我有一个包含多个级别的 XML。每个级别都可能附加有命名空间。我想要find一个我知道其名称但不知道其名称空间的特定元素。例如:

my_file.xml

<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="aaa:bbb:ccc:ddd:eee">
  <country name="Liechtenstein" xmlns="aaa:bbb:ccc:liechtenstein:eee">
    <rank updated="yes">2</rank>
    <year>2008</year>
    <gdppc>141100</gdppc>
    <neighbor name="Austria" direction="E"/>
    <neighbor name="Switzerland" direction="W"/>
  </country>
  <country name="Singapore" xmlns="aaa:bbb:ccc:singapore:eee">
    <continent>Asia</continent>
    <holidays>
      <christmas>Yes</christmas>
    </holidays>
    <rank updated="yes">5</rank>
    <year>2011</year>
    <gdppc>59900</gdppc>
    <neighbor name="Malaysia" direction="N"/>
  </country>
  <country name="Panama" xmlns="aaa:bbb:ccc:panama:eee">
    <rank updated="yes">69</rank>
    <year>2011</year>
    <gdppc>13600</gdppc>
    <neighbor name="Costa Rica" direction="W"/>
    <neighbor name="Colombia" direction="E"/>
  </country>
</data>
Run Code Online (Sandbox Code Playgroud)
import lxml.etree as etree

tree = etree.parse('my_file.xml')
root = tree.getroot()

cntry_node = root.find('.//country')

Run Code Online (Sandbox Code Playgroud)

上面的内容find不会返回任何内容cntry_node。在我的真实数据中,层次比这个例子更深。lxml 文档讨论了命名空间。当我这样做时:

root.nsmap
Run Code Online (Sandbox Code Playgroud)

我看到这个:

{None: 'aaa:bbb:ccc:ddd:eee'}
Run Code Online (Sandbox Code Playgroud)

如果有人可以解释如何访问完整内容nsmap和/或如何将其用于find特定元素?非常感谢。

Jac*_*ing 6

您可以声明所有名称空间,但考虑到示例 xml 的结构,我认为您最好完全忽略名称空间并仅使用local-name(); 所以

cntry_node = root.xpath('.//*[local-name()="country"]')
cntry_node
Run Code Online (Sandbox Code Playgroud)

回报

[<Element {aaa:bbb:ccc:liechtenstein:eee}country at 0x1cddf1d4680>,
 <Element {aaa:bbb:ccc:singapore:eee}country at 0x1cddf1d47c0>,
 <Element {aaa:bbb:ccc:panama:eee}country at 0x1cddf1d45c0>]
Run Code Online (Sandbox Code Playgroud)