我需要迭代一个对象列表并在xslt中对它们进行比较。如果找到匹配项,我需要停止处理该文档。如果我到达列表的末尾并且未找到匹配项,那么我需要处理该文档。 问题是xslt变量一旦声明就无法更改。这将是一个简单的For循环,在其他常见语言中使用true / false变量。
<!--I need to iterate through this list-->
<xsl:variable name="exclude">
<exclude block="999" />
<exclude block="111" />
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Here I iterate through the docs, but I don't iterate though the objects in the list.The main problem is I don't know how to search the list and make a decision at the end or when I encounter a match. This code only works on the first object "999" -->
<xsl:template match="/">
<xsl:if test="not(contains($url, exsl:node-set($exclude)/exclude/@block))">
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
答案 0 :(得分:0)
如果您正在使用XSLT 2.0,您可以在模板或函数中使用尾端递归,理想情况下使用主要的select-when-otherwise构造(when语句提供终止机制,否则准备下一个循环和调用本身)。
如果您使用的是3.0,请尝试使用xsl:iterate。
答案 1 :(得分:0)
您还没有显示输入文档,也没有设置变量以及您想要检查的内容但我认为您不需要任何迭代,如果您不想检查{ {1}}属性值包含在您的变量
中block
足以做到这一点。
我已经把三个样本放在
前两个匹配(参数<xsl:if test="not(exsl:node-set($exclude)/exclude/@block[contains($url, .)])">
分别是url
<xsl:param name="url">file://111</xsl:param>
)并且没有创建输出,最后一个匹配(<xsl:param name="url">file://999</xsl:param>
)和输出已创建。
因此,至少在正常XSLT 1设置的上下文中使用变量或参数,如图所示,该方法有效。
答案 2 :(得分:0)
这里有很多可能的策略。
通常,可以编写一个路径表达式来选择要处理的项目,并在xsl:for-each的select属性中使用它。
不起作用的情况是一个项目的处理(或终止的决定)取决于为先前项目计算的信息(以及每次重复计算的成本太高)。
在这种情况下,经典的解决方案是使用头尾递归:编写一个模板或函数,将项列表作为参数。模板/函数必须(a)决定是否继续处理(通常在输入列表为空时退出,但可能有其他终止条件),(b)处理第一个(“head”)项,以及(c)调用本身递归地处理列表的其余部分(“尾部”)。
在XSLT 3.0中有一个名为xsl:iterate的便捷指令,许多人发现这种指令更容易使用递归,因为它看起来更像传统的程序编程。它就像xsl:for-each,除了执行是严格顺序的,并且在处理了一个项目后,你设置了处理下一个项目时可用的参数;并且有一个xsl:break指令提前退出。
最后,在3.0中,您可以使用更高级别的左侧或右侧折叠功能的函数式编程方法。除非你从其他函数式编程语言来到XSLT,否则这可能不是你的首选。此外,它始终处理整个输入序列:没有提前退出的选项。