lxml - 默认名称空间

Sha*_*erz 3 python xml lxml

我正在尝试使用 .xml 解析一个 xml 文件lxml

my_tree = etree.parse(file)
my_root = my_tree.getroot()

for child in my_root:
    print(child.tag)

# {some default namespace}Prop
# {some default namespace}Prop
# {some default namespace}Stuff
# ...
Run Code Online (Sandbox Code Playgroud)

理想情况下,我只想用类似的东西获得我想要的所有元素

my_root.findall('Prop', my_root.nsmap)
Run Code Online (Sandbox Code Playgroud)

但这是返回一个空列表。我注意到my_root.nsmap字典有一个带有默认命名空间的 None 项目。

nsmap = {None: 'default namespace', ...}
Run Code Online (Sandbox Code Playgroud)

我通过复制 nsmap 并添加一个与 None 项目具有相同值的“默认”项目找到了一个快速解决方法,然后我做了

my_root.findall('default:Prop', new_map)
Run Code Online (Sandbox Code Playgroud)

这感觉非常hackish。为什么即使在命名空间映射中也没有?lxml 中是否有一些简单的方法可以自动使用默认命名空间?

编辑:我正在查看的 xml 是沿着

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ScenarioProps xmlns="http://filler.com/default.xsd" xmlns:ns2="http://filler.com/ns.xsd" id="Test">
    <Prop id="Wi-Fi">
        <ns2:Position x="0.0" y="0.0" z="0.0"/>
        <ns2:Orientation roll="0.0" pitch="0.0" yaw="0.0"/>
    </Prop>
</ScenarioProps>
Run Code Online (Sandbox Code Playgroud)

mzj*_*zjn 6

不管是不是黑客,你必须指定一个前缀。XPath 1.0是 lxml 支持的,它没有默认命名空间的概念(它在XPath 2.0 中的工作方式不同,但这不适用于此处)。

另一种选择是根本不打扰前缀。改用“克拉克符号”中的完全限定元素名称:

 my_root.findall('{http://filler.com/default.xsd}Prop').
Run Code Online (Sandbox Code Playgroud)

另请参阅http://lxml.de/FAQ.html#how-can-i-specify-a-default-namespace-for-xpath-expressions

2019 年 8 月更新

该行为在 lxml 的更高版本中发生了变化。在 lxml 4.4.1 中,None可以同时使用 和 空字符串:

from lxml import etree
 
my_tree = etree.parse("props.xml")
my_root = my_tree.getroot()
 
NS = 'http://filler.com/default.xsd'
 
NSMAP1 = {None: NS}
NSMAP2 = {'': NS}
NSMAP3 = {'default': NS}
 
print(my_root.findall('Prop', NSMAP1))
print(my_root.findall('Prop', NSMAP2))
print(my_root.findall('default:Prop', NSMAP3))
Run Code Online (Sandbox Code Playgroud)

输出:

[<Element {http://filler.com/default.xsd}Prop at 0x31f1260>]
[<Element {http://filler.com/default.xsd}Prop at 0x31f1288>]
[<Element {http://filler.com/default.xsd}Prop at 0x31f1260>]
Run Code Online (Sandbox Code Playgroud)