XPath 子遍历方法和性能

XPath Child Traversal Methods and Performance

我在 Python 2.7.

上使用 lxml

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

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

换句话说,这里发生了什么?有什么理由应该比另一个 "better"(在性能或正确性方面)?

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

这是个好问题,但不容易找到答案。

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

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

请参考以下代码,如有任何问题,请随时提出。

显示代码

设置:

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

结论

我不得不重写结论,因为在使用命名空间方法后,很明显使用命名空间的好处也在那里。指定命名空间(导致优化)比使用 local-name.

快大约 2 倍