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 倍
我在 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
.