为什么在XPath中“链接”比“ //链接”更快?

问题描述

给出此XML,

library(xml2)

text = paste0(
  '<?xml version="1.0" encoding="UTF-8"?><items>',paste(rep(
  '<item type="greeting" id="9273938">
     <link type="1" id="139" value="Hi"/>
     <link type="1" id="142" value="Hello"/>
   </item>',100),collapse = "\n"),'</items>')

x = xml_children(read_xml(text))

我可以使用"link""//link"选择所有链接节点,并获得相同的结果–但速度却大不相同:

bench::mark(
     link  = xml_find_all(x,"link"),`//link` = xml_find_all(x,"//link"))[1:5]

# A tibble: 2 x 5
  expression      min   median `itr/sec` mem_alloc
  <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>
1 link          1.5ms   1.56ms     606.     10.6KB
2 //link       27.1ms  55.74ms      15.2   558.2KB

为什么会有如此大的差异?

解决方法

因为"link"仅需要检查当前节点是否具有名为link的子元素,而"//link"则必须检查文档中的所有元素以查看哪些元素名为{{1 }}。

XPath注释:

  • link仅检查当前节点的直接子节点,因为 默认轴为"link"轴。
  • child::检查文档中的所有元素,因为"//link"//的快捷方式,因此/descendant-or-self::node()/"//link"的缩写。