0

我需要遍历对象列表并在 xslt 中比较它们。如果找到匹配项,我需要停止处理文档。如果我到达列表的末尾并且没有找到匹配项,那么我需要处理文档。问题是 xslt 变量一旦声明就不能更改。这将是一个简单的 For 循环,在其他常用语言中具有真/假变量。

     <!--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>
4

3 回答 3

0

如果您使用 XSLT 2.0,您可以在模板或函数中使用尾端递归,理想情况下使用主要的 choose-when-otherwise 构造(when 语句提供终止机制,否则准备下一个循环并调用自身)。

如果您使用的是 3.0,请尝试 xsl: iterate

于 2018-01-17T14:27:29.307 回答
0

您没有显示输入文档,也没有显示您如何设置变量以及您想要检查的确切内容,但我认为您不需要任何迭代,如果您想检查block变量中不包含任何属性值,那么

<xsl:if test="not(exsl:node-set($exclude)/exclude/@block[contains($url, .)])">

足以做到这一点。

我已经放了三个样品

  1. http://xsltfiddle.liberty-development.net/3Nqn5Y9
  2. http://xsltfiddle.liberty-development.net/3Nqn5Y9/1
  3. http://xsltfiddle.liberty-development.net/3Nqn5Y9/2

前两个匹配(参数分别为url)并且不创建输出,最后一个不匹配()并且创建输出。<xsl:param name="url">file://111</xsl:param><xsl:param name="url">file://999</xsl:param><xsl:param name="url">file://888</xsl:param>

因此,至少在带有变量或参数的普通 XSLT 1 设置的上下文中,该方法有效。

于 2018-01-17T15:04:38.993 回答
0

这里有很多可能的策略。

通常,可以编写一个路径表达式来选择要处理的项目,并在 xsl:for-each 的 select 属性中使用它。

这不起作用的情况是一个项目的处理(或终止的决定)取决于为先前项目计算的信息(并且每次重复计算的成本太高)。

在这种情况下,经典的解决方案是使用头尾递归:编写一个模板或函数,将项目列表作为参数。模板/函数必须(a)决定是否继续处理(通常在输入列表为空时退出,但其他终止条件也是可能的),(b)处理第一个(“头”)项,以及(c)调用本身递归地处理列表的其余部分(“尾部”)。

在 XSLT 3.0 中有一个名为 xsl:iterate 的便利指令,许多人发现使用该递归更容易,因为它看起来更像传统的过程编程。就像 xsl:for-each 一样,只是执行是严格按顺序执行的,在处理一个项目后,您设置在处理下一个项目时可用的参数;并且有一个用于提前退出的 xsl:break 指令。

最后,在 3.0 中,您可以使用更高级别的 fold-left 或 fold-right 函数的函数式编程方法。除非您是从其他函数式编程语言开始使用 XSLT,否则这可能不是您的首选。此外,它总是处理整个输入序列:没有提前退出的选项。

于 2018-01-17T15:58:17.987 回答