XPath子遍历方法和性能

时间:2015-07-13 19:45:10

标签: python xml lxml

我在Python 2.7上使用lxml。

给定一个节点node和一个子节点child_element,它们之间有什么区别: node.xpath('./child_element')

node.xpath("*[local-name()='child_element']")

换句话说,这里引人注目的是什么?有什么理由应该是"更好"比另一个(在表现或正确性方面)?

我已经阅读了lxml文档和大量其他XPath查询资源,但没有找到任何真正的说明。

1 个答案:

答案 0 :(得分:2)

这是一个很好的问题,不容易找到答案。

主要区别在于local-name() 考虑标记的前缀(名称空间)。

例如,给定节点<x:html xmlns:x="http://www.w3.org/1999/xhtml"/>local-name将与html标记匹配,而//html将不起作用,//x:html也不会。

如果您有任何问题,请考虑以下代码。

显示代码

设定:

from lxml.etree import fromstring
tree = fromstring('<x:html xmlns:x="http://www.w3.org/1999/xhtml"/>')

现在无法使用标签选择器:

tree.xpath('//html')
# []

tree.xpath('//x:html')
# XPathEvalError: Undefined namespace prefix

但是使用local-name我们仍然可以获得元素(考虑命名空间)

tree.xpath('//*[local-name() = "html"]')
# [<Element {http://www.w3.org/1999/xhtml}html at 0x103b8d848>]

使用name()严格命名空间:

tree.xpath('//*[name() = "x:html"]')
# [<Element {http://www.w3.org/1999/xhtml}html at 0x103b8d848>]

效果

我将此网站解析为树,并使用以下查询:

%timeit tree.xpath('//*[local-name() = "div"]')
# 1000 loops, best of 3: 570 µs per loop

%timeit tree.xpath('//div')
# 10000 loops, best of 3: 44.4 µs per loop

现在进入实际的名称空间。我从here解析了一个块。

example = """ ... """
from lxml.etree import fromstring
tree = fromstring(example)

%timeit tree.xpath('//hr:author', 
                   namespaces = {'hr' : 'http://eric.van-der-vlist.com/ns/person'})
# 100000 loops, best of 3: 18.2 µs per loop

%timeit tree.xpath('//*[local-name() = "author"]')
# 10000 loops, best of 3: 37.7 µs per loop

结论

我不得不重写结论,因为在使用命名空间方法后,很明显使用命名空间时的增益也存在。指定命名空间(导致优化)时,大约快2倍,而不是使用local-name