xslt перебирает весь список или до совпадения

Мне нужно перебрать список объектов и сравнить их в 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>

3 ответа

Решение

Вы не показали входной документ, ни то, как вы настраивали переменную, и что именно вы хотите проверить, но я не думаю, что вам нужна какая-либо итерация, если вы хотите проверить, что ни один из 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 с переменной или параметром, как показано, подход работает.

Если вы используете XSLT 2.0, вы можете использовать хвостовую рекурсию в шаблоне или функции, в идеале с первичной конструкцией выбора, когда иным (операторы when, обеспечивающие механизм завершения, и в противном случае подготовка следующего цикла и сам вызов).

Если вы используете 3.0, попробуйте xsl: iterate.

Здесь довольно много возможных стратегий.

Часто можно написать выражение пути, которое выбирает элементы, которые вы хотите обработать, и использовать это в атрибуте select xsl:for-each.

Случай, когда это не работает, - это когда обработка одного элемента (или решение прекратить) зависит от информации, вычисленной для предыдущих элементов (и когда повторение вычисления слишком дорого каждый раз).

Классическим решением в этом случае является использование рекурсии head-tail: напишите шаблон или функцию, которая принимает список элементов в качестве параметра. Шаблон / функция должны (а) решить, продолжать ли обработку (обычно она завершается, когда список ввода пуст, но возможны другие условия завершения), (б) обрабатывает первый ("головной") элемент и (в) вызывать сам рекурсивно обрабатывать остальную часть списка ("хвост").

В XSLT 3.0 есть удобная инструкция под названием xsl:iterate, которую многие люди находят проще в использовании этой рекурсии, потому что она больше похожа на обычное процедурное программирование. Это похоже на xsl: for-each, за исключением того, что выполнение строго последовательное, и после обработки одного элемента вы устанавливаете параметры, которые доступны при обработке следующего элемента; и есть инструкция xsl:break для досрочного выхода.

Наконец, в версии 3.0 вы можете использовать функциональный подход к программированию функции сложения влево или вправо. Если вы не пришли в XSLT с других языков функционального программирования, это, вероятно, не будет вашим первым выбором. Кроме того, он всегда обрабатывает всю последовательность ввода: нет возможности для досрочного выхода.

Другие вопросы по тегам