我在Python 2.7上使用lxml。
给定一个节点node
和一个子节点child_element
,它们之间有什么区别:
node.xpath('./child_element')
node.xpath("*[local-name()='child_element']")
换句话说,这里引人注目的是什么?有什么理由应该是"更好"比另一个(在表现或正确性方面)?
我已经阅读了lxml文档和大量其他XPath查询资源,但没有找到任何真正的说明。
答案 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
。