Подтвердить что ты не робот

XSLT: соединение от 1 до 60

Каков наилучший способ для цикла в XSLT от 1 до 60? Я исследую в сети, есть некоторые шаблоны для этого, есть ли другой способ, например, как встроенная функция?

4b9b3361

Ответ 1

В XSLT 2.0

<xsl:for-each select="1 to 60">...</xsl:for-each>

Но я предполагаю, что вы должны использовать XSLT 1.0, иначе вы не спросите.

В XSLT 1.0 вы должны использовать рекурсию: шаблон, который вызывает себя с помощью счетчика, который увеличивается на каждый вызов, и рекурсия завершается, когда достигается требуемое значение.

В качестве альтернативы существует обходной путь в XSLT 1.0: если ваш исходный документ содержит не менее 60 узлов, вы можете сделать

<xsl:for-each select="(//node())[60 >= position()]">...</xsl:for-each>

Ответ 2

Проблема с простой рекурсией при обработке длинных последовательностей заключается в том, что часто для стека вызовов становится недостаточно, и обработка заканчивается из-за. Обычно это происходит с длиной последовательности >= 1000.

Общий способ избежать этого (реализуемый с любым XSLT-процессором, даже если он не распознает хвостовую рекурсию) является рекурсией стиля DVC (Divide и Conquer).

Вот пример преобразования, которое успешно печатает числа от 1 до 1000000 (1M):

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>

     <xsl:template match="/">
      <xsl:call-template name="displayNumbers">
        <xsl:with-param name="pStart" select="1"/>
        <xsl:with-param name="pEnd" select="1000000"/>
      </xsl:call-template>
     </xsl:template>

     <xsl:template name="displayNumbers">
      <xsl:param name="pStart"/>
      <xsl:param name="pEnd"/>

      <xsl:if test="not($pStart > $pEnd)">
       <xsl:choose>
        <xsl:when test="$pStart = $pEnd">
          <xsl:value-of select="$pStart"/>
          <xsl:text>&#xA;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="vMid" select=
           "floor(($pStart + $pEnd) div 2)"/>
          <xsl:call-template name="displayNumbers">
           <xsl:with-param name="pStart" select="$pStart"/>
           <xsl:with-param name="pEnd" select="$vMid"/>
          </xsl:call-template>
          <xsl:call-template name="displayNumbers">
           <xsl:with-param name="pStart" select="$vMid+1"/>
           <xsl:with-param name="pEnd" select="$pEnd"/>
          </xsl:call-template>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:if>
     </xsl:template>
</xsl:stylesheet>

При применении к любому XML-документу (не используется) это преобразование создает желаемый результат - все числа от 1 до 1000000.

Вы можете использовать/адаптировать это преобразование для любой задачи, которая должна "делать что-то N раз".

Ответ 3

Очень простая проверка внутри цикла foreach

<xsl:if test="$maxItems > position()">
    do something
</xsl:if>

На основе ответа Димитрия Новачева.

Пример:

<xsl:variable name="maxItems" select="10" />
<xsl:variable name="sequence" select="any-sequence"/>

<xsl:for-each select="$sequence">

    <!-- Maybe sort first -->
    <xsl:sort select="@sort-by" order="descending" />

    <!-- where the magic happens -->
    <xsl:if test="$maxItems > position()">
        do something
    </xsl:if>
</xsl:for-each>

Ответ 4

XSLT работает на основе шаблонов, и вам понадобится шаблон для запуска этого цикла.

Вам нужно будет создать шаблон, принимающий начальные и конечные значения, а внутри него сделать вычисления с рекурсивным вызовом с помощью start + 1. Когда $start равно $end, вы возвращаете свой шаблон без другого вызова.

На практике: http://www.ibm.com/developerworks/xml/library/x-tiploop/index.html