带有尾随“[1]”或“[last()]`谓词

时间:2017-03-09 08:58:01

标签: xpath xslt-2.0 saxon

这个问题具体是关于在XSLT 2.0和Saxon中使用XPath。

[1]

结尾的XPath

对于像

这样的XPath
following-sibling::foo[1]
descendant::bar[1]

我认为Saxon不会在整个轴上进行迭代,但在找到第一个匹配节点时停止 - 在以下情况下至关重要:

following-sibling::foo[some:expensivePredicate(.)][1]

我认为这样的XPath也是如此:

(following-sibling::foo/descendant::bar)[1]

即。在选择集合中的第一个节点之前,Saxon不会编译匹配following-sibling::foo/descendant::bar的整个节点集。相反,它(即使对于链式轴)也会停在第一个匹配节点上。

[last()]

结尾的XPath

现在它变得有趣了。什么时候去"倒退"在树中,我假设XPath喜欢

preceding-sibling::foo[1]

与其following-sibling等价物一样有效。但是当链接轴时会发生什么,例如

(preceding-sibling::foo/descendant::bar)[last()]

我们需要在此使用[last()]代替[1]

  • Saxon会编译整个节点集来计算它们以获得last()的数值吗?
  • 或者它是否聪明并且在找到匹配的后代时停止迭代preceding-sibling轴?
  • 或者它会更加聪明并反向迭代descendant轴以更有效地找到最后一个后代?

1 个答案:

答案 0 :(得分:1)

Saxon有各种评估package additiveprimes; import java.util.Arrays; import java.util.Scanner; /** * * @author talarik048 */ public class AdditivePrimes { public static void main(String[] args){ AdditivePrimes additivePrime = new AdditivePrimes(); additivePrime.userInput(x); additivePrime.isPrime(x); additivePrime.numArray(x); } public void userInput(String x){ Scanner sc = new Scanner(System.in); try{ System.out.println("Please enter a number: "); x = sc.nextLine(); } catch(NumberFormatException e){ System.out.println("Error, try again: "); x = sc.nextLine(); } } public void isPrime(String x){ this.userInput(x); boolean prime = true; int y = Integer.parseInt(x); for(int i = 0; i < y; i++){ if(y % i == 0){ prime = false; break; } if(prime){ System.out.println("Your number is prime..."); } else { System.out.println("Your number is not prime..."); } } } public void numArray(String x){ this.userInput(x); String[] strArray = x.split("\\s+"); boolean prime = true; int[] numbArray = new int[strArray.length]; for(int j = 0; j < strArray.length; j++){ try{ numbArray[j] = Integer.parseInt(strArray[j]); } catch(NumberFormatException e){ System.out.println("ERROR"); } for(int i = 0; i < numbArray.length; i++){ int sum = (Arrays.stream(numbArray).sum()); if(sum % i == 0){ prime = false; break; } if(prime){ System.out.println("Your number is an additive prime..."); } else { System.out.println("Your number is not an additive prime..."); } } } } } 的策略。当用作谓词时,意味着last(),它通常被转换为内部函数[position()=last()],可以通过单项预测进行评估。 (所以在你的[isLast()]示例中,它并没有在内存中构建节点集,而是逐个读取节点,当它到达结尾时,返回它找到的最后一个节点集)。

在其他情况下,特别是在XSLT匹配模式中使用时,Saxon会将(preceding-sibling::foo /descendant::bar)[last()]转换为child::x[last()]

当这些方法都不起作用时,多年来,Saxon根据应用的表达式有两种评估child::x[not(following-sibling::x)]的策略:(a)有时它会对表达式进行两次评估,第一次计算节点和第二次归还他们; (b)在其他情况下,它会将所有节点读入内存。我们最近遇到了策略(a)失败的情况:请参阅https://saxonica.plan.io/issues/3122,因此我们一直在做(b)。

last()表达式可能很昂贵,应该尽可能避免。例如,经典&#34;在相邻的项目之间插入一个分隔符&#34;这通常是写的

last()

更好地写成

xx
if (position() != last()) sep

即。而不是在除了最后一项之外的每个项之后插入分隔符,而是在除第一项之外的每个项之前插入它或者使用if (position() != 1) sep xx string-join