我正在尝试使用lxml
解析xml文件。
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
# ...
理想情况下,我只想用
之类的东西获得我想要的所有元素my_root.findall('Prop', my_root.nsmap)
但这会返回一个空列表。我注意到my_root.nsmap
字典有一个带有默认命名空间的无项。
nsmap = {None: 'default namespace', ...}
我通过复制nsmap并添加一个与“无”项目具有相同值的“默认”项目找到了一个快速的解决方法,然后我做了
my_root.findall('default:Prop', new_map)
这感觉非常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>
答案 0 :(得分:2)
我只是使用帮助类。 context
是文档,my
是命名空间,key
是标记名称。
found = self.context.find('.//{%s}%s' % (self.my, key))
答案 1 :(得分:2)
是否哈希,你必须指定一个前缀。 XPath 1.0 ,这是lxml支持的,没有默认命名空间的概念(它在 XPath 2.0中的工作方式不同,但这不适用于此处。)
另一个选择是根本不打扰前缀。请改为使用“Clark表示法”中的完全限定元素名称:
my_root.findall('{http://filler.com/default.xsd}Prop').
另见http://lxml.de/FAQ.html#how-can-i-specify-a-default-namespace-for-xpath-expressions。
答案 2 :(得分:2)
你可以自动&#34;用以下内容重新定义默认命名空间:
{k if k is not None else 'default':v for k,v in my_root.nsmap.items()}
获取一个命名空间字典,其中的密钥None替换为&#34;默认&#34;并保持所有其他键不受影响:
{'default': 'http://filler.com/default.xsd', 'ns2': 'http://filler.com/ns.xsd'}
您的示例如下所示:
from lxml import etree
import StringIO
f = StringIO.StringIO('''
<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>
''')
parser = etree.XMLParser()
my_tree = etree.parse(f, parser)
my_root = my_tree.getroot()
my_tree.getroot().nsmap
nsmap = {k if k is not None else 'default':v for k,v in my_root.nsmap.items()}
my_root.findall('default:Prop', nsmap)