为什么 "link" 在 XPath 中比 "//link" 快?

Why is "link" faster than "//link" in 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" select 所有 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" 必须检查文档中的所有元素以查看哪些元素名为 link.

XPath 注释:

  • "link" 只检查当前节点的直接子节点,因为 默认轴是 child:: 轴。
  • "//link"检查文档中的所有元素,因为///descendant-or-self::node()/的简写,所以"//link"/descendant-or-self::node()/child::link.[=30的简写=]