在具有不一致的命名空间声明的文档上使用iterparse,然后使用xpath

时间:2012-09-08 16:46:53

标签: python xml-parsing lxml xml-namespaces iterparse

我需要整理一段代码,将可能很大的XML文件解析为自定义Python对象。这个想法大致如下:

from lxml import etree
for e, tag in etree.iterparse(source, tag='Foo'):
    print tag.xpath('bar/baz')[42] # there's actually a function call here
问题是,一些文档有一个名称空间声明,有些文档没有。这意味着在上面的代码中,tag='Foo'xpath部分都无效。

现在我一直在忍受丑陋的

for e, tag in etree.iterparse(source):
    if tag.tag.endswith('Foo'):
        print tag.xpath('*[local-name()="bar"]/*[local-name()="baz"]')[42]

但是这太可怕了,即使它工作正常我也想要把它弄好。 (我想它也应该慢一些。)

有没有办法编写使用iterparse来解决这两种情况的合理代码? 现在我只能考虑捕获start-nsend-ns事件并更新“状态保持”变量,我必须将其传递给在循环内调用的函数来完成工作。然后,该函数将相应地构造xpath个查询。这有点道理,但我想知道是否有更简单的方法。

P.S。我显然已经尝试过搜索,但是没有找到一个既可以使用也可以不使用命名空间的解决方案。我也接受一个消除XML命名空间的解决方案,但前提是它不会在整个过程中将整个树存储在RAM中。

1 个答案:

答案 0 :(得分:2)

所有元素都有.nsmap映射属性;用它来检测命名空间并相应地进行分支。