如何检查XSLT语句是否已执行

时间:2016-04-25 15:18:56

标签: xml xslt xslt-1.0

我的XSLT中有一个for-each语句,里面有一个if条件。我需要在if条件成立时第一次执行一条语句。

<xsl:for-each select="">
    <!-- if condition true -->
        <!-- DO SOMETHING -->
        <!-- if its the first entry in the if condition do something -->
    <!-- End If -->
</xsl:for-each>`

我无法使用任何变量将值设置为true false,因为变量是XSLT中的常量。有没有办法实现这个目标?

3 个答案:

答案 0 :(得分:1)

你不能谈论&#34;第一次执行某些事情&#34;使用像XSLT这样的函数式语言。没有已定义或可检测的执行顺序。 xsl:for-each不是循环结构,它是一个映射构造:它将相同的函数(for-each body)应用于输入序列中的每个项目,在概念上并行(在某些实现中,实际上并行) )。

因此,您要特别处理的项目不是处理顺序中满足某些条件的第一项,而是输入序列中满足该条件的第一项。

您尚未准确说明要求,以便在您的具体情况下了解理想的答案,但您可以使用的一些技巧是:

(a)使用选择表达式中的谓词更精确地选择要处理的项目集:<xsl:for-each select="nodes[predicate]">

(b)使用<xsl:if test="position()=1">

特别处理第一个选定项目

(c)预先评估使某些节点特殊的条件,并在for-each中对此进行测试:

<xsl:variable name="special-nodes" select="...."/>
<xsl:variable name="first-special-node" select="$special-nodes[1]"/>
<xsl:for-each select="selected-nodes">
  <xsl:if test=". is $first-special-node">....

(那是2.0的语法;在1.0中使用generate-id()比较节点。)

(d)使用递归而不是每次递归。递归的经典方法是编写一个以序列作为输入的模板。如果序列中至少有一个项目,则递归模板会对其执行某些操作,然后调用自身来处理&#34; tail&#34;序列,命名空间除第一个以外的所有项目。使用这种方法,项目确实按顺序处理,您可以通过递归调用传递其他参数,以指示,例如,第一个&#34;特殊&#34;已找到并处理该项目。

答案 1 :(得分:0)

你的思维过于程序化。在XSLT中,它有助于以声明方式进行思考。而不是尝试设置标志,而是针对输入文档测试条件。

例如,在您的情况下,您可以测试项目的位置,

    <xsl:if test="position() = 1">

而不是设置标志。

您可以进一步考虑通过for-each进行循环是否是实现目标的最佳方式;通常,apply-templates可以更好地调用与输入文档中的节点匹配的相关模板。

更新:您可以将条件移至select,如果您希望第一个位置测试仅适用于position() = 1 条件适用的第一种情况。

<xsl:for-each select="original_select_AND_CONDITION">
    <!-- do something for all cases -->
    <xsl:if test="position() = 1">
        <!-- do something for first case -->
    </xsl:if>
</xsl:for-each>`

答案 2 :(得分:0)

你的问题太模糊了。从字面上理解你的要求:

  

我需要在第一次if时执行一段语句   条件是真的。

你必须做类似的事情:

<xsl:for-each select="some-nodes">
    <xsl:if test="condition=true()">
        <!-- DO SOMETHING -->
        <!-- if its the first entry in the if condition do something -->
        <xsl:if test="not(following-sibling::some-nodes[condition=true()])">
            <!-- DO SOMETHING ADDITIONAL -->
        </xsl:if>
    </xsl:if>
</xsl:for-each>

这是非常低效的,因为它需要重复测试每个节点的所有以下兄弟节点。

最好只处理满足条件的节点,然后挑出第一个节点,例如:

<xsl:for-each select="some-nodes[condition=true()]">
    <!-- DO SOMETHING -->
    <!-- if its the first entry in the if condition do something -->
    <xsl:if test="position() = 1">
        <!-- DO SOMETHING ADDITIONAL -->
    </xsl:if>
</xsl:for-each>

有选择地应用模板并为每个案例使用单独的模板可能会更好 - 但我们对您的目的不够了解。