我正在尝试使用 .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)
不管是不是黑客,你必须指定一个前缀。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。
该行为在 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)