我正在开发一个XSLT1.0样式表(并使用xsltproc应用它)。我的脚本中的一个模板应该对给定父节点中的第一个<sect1>
元素和最后一个<sect1>
元素执行一些特殊处理。现在这个特殊的处理是这样实现的:
<xsl:template match="sect1">
<xsl:if test="not(preceding-sibling::sect1)">
<!-- Special handling for first sect1 element goes here. -->
</xsl:if>
<!-- Common handling for all sect1 elements goes here. -->
<xsl:if test="not(following-sibling::sect1)">
<!-- Special handling for last sect1 element goes here. -->
</xsl:if>
</xsl:template>
我想知道(只是出于好奇,脚本的运行速度对我来说很好):有没有更有效的方法来做到这一点?在找到第一个匹配项之后,XSLT处理器是否可能会停止组装preceding-sibling::sect1
节点集,因为它知道只需要找到一个或零个元素?
发布于 2010-09-04 03:56:48
处理器是否会在找到第一个匹配项后停止组装之前的兄弟::Sect1节点集,因为它知道它只需要找到一个或零个元素?
我不知道xsltproc,但是Saxon非常擅长这些优化。我相信它只会检查第一个找到的匹配项,因为它只需要知道节点集是否为空。
但是,您始终可以通过如下更改测试来确保:
<xsl:if test="not(preceding-sibling::sect1[1])">
和
<xsl:if test="not(following-sibling::sect1[1])">
因为这将只测试每个轴上的第一个同级。请注意,每种情况下的1都是指XPath步骤的顺序,这是轴的顺序,不一定是文档顺序。因此,preceding-sibling::sect1[1]
引用的是紧挨着当前元素的sect1同级元素,而不是文档顺序中的第一个sect1同级元素。因为preceding-sibling
轴的方向是相反的。
发布于 2010-08-27 13:52:03
假设在其中调用模板的上下文是一个子节点选择,那么我将提供以下内容。如果它们被调用的上下文是通过一个不同的轴(比如前面的兄弟或祖先),那么处理它的方法就是最好的。
两种可能性是简化测试,或者用不同的模板替换它们:
更简单的测试:
<xsl:template match="sect1">
<xsl:if test="position() = 1">
<!-- Special handling for first sect1 element goes here. -->
</xsl:if>
<!-- Common handling for all sect1 elements goes here. -->
<xsl:if test="position() = last()">
<!-- Special handling for last sect1 element goes here. -->
</xsl:if>
</xsl:template>
不同的模板:
<xsl:template name="handleSect1">
<!-- Common handling for all sect1 elements goes here. -->
<xsl:template>
<xsl:template match="sect1">
<xsl:call-template name="handleSect1"/>
</xsl:template>
<xsl:template match="sect1[1]">
<!-- Special handling for first sect1 element goes here. -->
<xsl:call-template name="handleSect1"/>
</xsl:template>
<xsl:template match="sect1[last()]">
<xsl:call-template name="handleSect1"/>
<!-- Special handling for last sect1 element goes here. -->
</xsl:template>
<xsl:template match="sect1[position() = 1 and position() = last()]">
<!-- Special handling for first sect1 element goes here. -->
<xsl:call-template name="handleSect1"/>
<!-- Special handling for last sect1 element goes here. -->
</xsl:template>
既然你说“优化”,我假设你关心的是哪一个会处理得更快。它将根据xslt处理器、处理模式(有些有一个“编译”选项,这将影响哪个更有效)和输入XML而有所不同。最快的可能是这两个或你原来的。
实际上,其中的每一个都应该是高效的,不同之处在于处理器设法进行的优化。
在这种情况下,我会倾向于第一个答案,因为它是最简洁的,但如果我不想在所有4个案例之间共享共同的处理,我会倾向于第二个答案中的方法,然后清楚地标记每个案例的不同方法。
发布于 2010-08-27 13:40:35
我认为你应该能够做到
<xsl:if test="position() = 1">
<!-- Special handling for first sect1 element goes here. -->
</xsl:if>
<!-- Common handling for all sect1 elements goes here. -->
<xsl:if test="position() = last()">
<!-- Special handling for last sect1 element goes here. -->
</xsl:if>
因为position()
和last()
是上下文敏感。
https://stackoverflow.com/questions/3584645
复制相似问题