与 XPath 表达式相比,非流模式下的 XSLT 3 累加器是不是提供性能优势?
Posted
技术标签:
【中文标题】与 XPath 表达式相比,非流模式下的 XSLT 3 累加器是不是提供性能优势?【英文标题】:Do XSLT 3 accumulators in non-streaming mode provide a performance benefit compared to XPath expressions?与 XPath 表达式相比,非流模式下的 XSLT 3 累加器是否提供性能优势? 【发布时间】:2021-05-30 08:18:51 【问题描述】:假设我有一个这样的文档:
<persons>
<person age="14" name="John"/>
<person age="23" name="Rob"/>
...
</persons>
我想找到列表中最年轻的人。
看来我可以用一个普通的 XPath 表达式(类似于//person[@age=min(//person/@age)]
)来做到这一点。在 XSLT 3 中,我还可以像这样编写一个累加器:
<xsl:accumulator name="acc" initial-value="()">
<xsl:accumulator-rule match="person" select="if(@age < $value/@age) then . else $value"/>
</xsl:accumulator>
然后在我需要的时候拨打accumulator-after('acc')
。
在非流媒体环境中,使用其中一个是否有好处?我认为,至少,使用累加器可以使我免于编写可能效率低下的 XPath 表达式。或者一个复杂的 XPath 处理器(在我的例子中是 Saxon)是否会将查询优化为相当于使用累加器,因此我如何做到这一点并不重要?
【问题讨论】:
【参考方案1】:累加器可能比常规 XPath 表达式更快的情况是,您需要为文档中的许多节点计算一些值(例如,节号或年初至今的总数),并且节点 N 的值可以方便地表示为较早节点的值的函数。 xsl:number 是一个经典案例。但是您也可以使用 XSLT 3.0 备忘录函数来实现这一点。
如果您的 XPath 表达式使用前面的轴,那么这就是累加器可能提供帮助的信号。
【讨论】:
【参考方案2】:到目前为止,我能想到的最“创造性”的不带流的累加器使用是在尝试使用 XPath 3.1 函数 random-number-generator
时,如果你想使用 ?next()
函数有点棘手为树中的某些节点处理它,累加器使这变得容易,例如:
<xsl:accumulator name="random-number" as="map(*)" initial-value="random-number-generator(current-dateTime())">
<xsl:accumulator-rule match="*" select="$value?next()"/>
</xsl:accumulator>
并像在例如中一样使用它
<xsl:template match="*">
<xsl:comment select="accumulator-before('random-number')?number"/>
<xsl:next-match/>
</xsl:template>
这种处理不需要单个值,但需要为树中的某些匹配节点计算一个值,其中下一个节点的值取决于前一个节点的值,这种处理是使用累加器而不使用流式传输其中单个 XPath 表达式可能更难,或者如果不使用累加器,则需要在 XSLT 2 或 3 中使用隧道参数。
【讨论】:
以上是关于与 XPath 表达式相比,非流模式下的 XSLT 3 累加器是不是提供性能优势?的主要内容,如果未能解决你的问题,请参考以下文章
使用带有多个表达式的祖先或自我选择 text() XSLT XPATH