lxml - 默认名称空间

时间:2016-07-21 17:27:53

标签: python xml lxml

我正在尝试使用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>

3 个答案:

答案 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)