我的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中的常量。有没有办法实现这个目标?
答案 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>
有选择地应用模板并为每个案例使用单独的模板可能会更好 - 但我们对您的目的不够了解。