Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有尾随“[1]”或“[last()]”谓词的链接XPath轴_Xpath_Xslt 2.0_Saxon - Fatal编程技术网

带有尾随“[1]”或“[last()]”谓词的链接XPath轴

带有尾随“[1]”或“[last()]”谓词的链接XPath轴,xpath,xslt-2.0,saxon,Xpath,Xslt 2.0,Saxon,这个问题是关于在XSLT2.0和Saxon中使用XPath的 以[1]结尾的XPath 对于像这样的XPath following-sibling::foo[1] descendant::bar[1] preceding-sibling::foo[1] 我想当然地认为,Saxon不会在整个轴上迭代,而是在找到第一个匹配节点时停止,这在以下情况下至关重要: following-sibling::foo[some:expensivePredicate(.)][1] 我假设XPath也是这样

这个问题是关于在XSLT2.0和Saxon中使用XPath的

以[1]结尾的XPath 对于像这样的XPath

following-sibling::foo[1]
descendant::bar[1]
preceding-sibling::foo[1]
我想当然地认为,Saxon不会在整个轴上迭代,而是在找到第一个匹配节点时停止,这在以下情况下至关重要:

following-sibling::foo[some:expensivePredicate(.)][1]
 
我假设XPath也是这样:

(following-sibling::foo/descendant::bar)[1]
也就是说,在选择集合中的第一个节点之前,Saxon不会编译匹配以下兄弟节点::foo/后代::bar的整个集合。相反,即使对于链接轴,它也会在第一个匹配节点处停止

以[last]结尾的XPath 现在它变得有趣了。当在树中向后走时,我假设XPath像

following-sibling::foo[1]
descendant::bar[1]
preceding-sibling::foo[1]
与他们的以下兄弟姐妹同等有效地工作。但是当链接轴时会发生什么,例如

(preceding-sibling::foo/descendant::bar)[last()]
因为我们需要在这里使用[last]而不是[1]

Saxon是否会编译整个节点集,对它们进行计数,以获得最后一个节点的数值? 或者,当它找到匹配的子代时,它会智能地停止迭代前面的同级轴吗? 或者它会更聪明,反向迭代子体轴以更有效地找到最后一个子体?
撒克逊人有各种各样的策略来评估最后的结果。当用作谓词时,表示[position=last],它通常被转换为一个内部函数[isLast],该函数可由一个单独的项先行计算。因此,在前面的sibling::foo/genderant::bar[last]示例中,它不会在内存中构建节点集,而是逐个读取节点,当到达末尾时,返回找到的最后一个节点

在其他情况下,特别是在XSLT匹配模式中使用时,Saxon会将child::x[last]转换为child::x[notfollowing sibling::x]

当这些方法都不起作用时,多年来,Saxon有两种策略用于根据应用于的表达式进行最后计算:a有时会计算表达式两次,第一次计算节点数,第二次返回节点数;b在其他情况下,它会将所有节点读入内存。我们最近遇到了策略a失败的案例:看,所以我们一直在做b


最后一个表达式可能代价高昂,应尽可能避免使用。例如,经典的在相邻项目之间插入一个分隔符,该分隔符通常是书写的

xx
if (position() != last()) sep
写得比写得好得多

if (position() != 1) sep
xx

i、 e.不要在除最后一项之外的每项之后插入分隔符,而是在除第一项之外的每项之前插入分隔符。或者使用字符串连接,或者xsl:value of/@separator。

最后一个表达式可能很昂贵——这是我的直觉,我希望可以消除它。回顾前面的兄弟::foo/genderant::bar[last]在应用于大型数据集中的每个元素时,可能会执行On²。对于我的应用程序,基于具有前瞻性使用属性的键可能会有另一种选择,这将以二次性能换取线性内存使用。在大型数据集上仍然不理想,但可管理。在循环中使用轴,如后面的[-sibling]或前面的[-sibling],都可能具有二次性能,通常谓词[last]不会使其更好。您还需要考虑是否会对文档顺序进行排序-使用-explain查看执行计划可能会有所启示。这可能取决于数据的结构,对吗?我想当我知道1时,我可以假设以下查询的线性性能为sibling::foo/genderant::bar[1]。具有匹配子代的第一个后续兄弟最多相隔5个节点,与总数据集的大小无关,2个。每个查询的子体轴的大小也大致保持不变,与总数据集的大小无关。