我在 Python 2.7 上使用 lxml。
给定一个节点 node
和一个子节点 child_element
,它们之间有什么区别:
node.xpath('./child_element')
node.xpath("*[local-name()='child_element']")
换句话说,这里到底发生了什么?是否有任何理由认为一个人应该比另一个人“更好”(在性能或正确性方面)?
我已经阅读了 lxml 文档和大量其他 XPath 查询资源,但没有找到任何真正的说明。
最佳答案
这是一个很好的问题,但不容易找到答案。
主要区别是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 中的一个 block .
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
.
关于python - XPath 子级遍历方法和性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31392089/