【问题标题】:xslt iterate through a whole list or until matchxslt 遍历整个列表或直到匹配
【发布时间】:2018-01-17 13:40:00
【问题描述】:

我需要遍历对象列表并在 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>

【问题讨论】:

  • 什么是$url,输入文档看起来如何,在将输入映射到输出方面,您想要的结果是什么?
  • $url 只是文档中的一个 url。它看起来像 它可能看起来很奇怪,但它是我正在使用的系统的一部分。“/”上的匹配基本上是根 节点上的匹配。我需要阻止在其 url 中包含特定值的文档。我可以让它在“999”而不是“111”上工作,因为我无法迭代整个排除列表。我会有 200-400 个排除节点。
  • 顺便说一句,这一切都必须在 XSLT 1.0 中

标签: xml xslt watson-explorer


【解决方案1】:

您没有显示输入文档,也没有显示您如何设置变量以及您想要检查的确切内容,但我认为您不需要任何迭代,如果您想检查 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 分别为&lt;xsl:param name="url"&gt;file://111&lt;/xsl:param&gt;&lt;xsl:param name="url"&gt;file://999&lt;/xsl:param&gt;)并且不创建输出,最后一个不匹配(&lt;xsl:param name="url"&gt;file://888&lt;/xsl:param&gt;)并创建输出。

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

【讨论】:

  • 你说得对,我想。我仍然无法让代码正确处理。该文档看起来像这样 Blah blah。当应用为 请记住 $url 是系统的一部分。我知道那是事实上的 file://111
  • 我已经编辑了答案并提供了指向 XSLT 1 的链接,我的建议和参数 url 预设为不同的值,我认为它们可以满足您的需求。所以不知何故你的环境一定是不同的。
  • 哇,这个解决方案太完美了。我必须让它在我的系统中工作,但你证明我不需要迭代。谢谢!
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    这里有很多可能的策略。

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      • 2016-08-08
      • 2021-03-19
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多