цикл for на странице xslt - PullRequest
1 голос
/ 02 января 2012

Я получаю из моего xml целое число и хочу получить все числа от 1 до полученного числа.

Я хочу вставить эти числа как имена столбцов.

Можно ли это сделать?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 02 января 2012

I.Решение XSLT 2.0 :

 <xsl:sequence select="1 to $N"/>

II.Решение XSLT 1.0 DVC

Ответ @nd (с использованием примитивной рекурсии) является хорошим.

Однако, если последовательность чисел должна быть сгенерирована с достаточнопримитивная рекурсия большой длины (1000 и более) обычно заканчивается ненормально с переполнением стека из-за слишком глубокой рекурсии.

Метод DVC (Divide and Conquer) можно использовать, чтобы избежать переполнения стека вызововдля любого практического случая :

<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 (не используется), он выводит числа от одного до одного миллиона .Максимальная глубина стека вызовов во время этого преобразования составляет всего 19 (log2 (N)).


III.Нерекурсивное решение XSLT 1.0 :

В случае, если длина генерируемой числовой последовательности не слишком велика (точнее, не превышает количество доступныхузлы в документе XML (например, сама таблица стилей XSLT)), , тогда мы можем использовать нерекурсивное решение, известное как Piez метод :

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

 <xsl:variable name="vDoc" select="document('')"/>
 <xsl:variable name="vNodes" select=
 "$vDoc//node() | $vDoc//@* | $vDoc//namespace::*"/>

 <xsl:template match="/">
     <xsl:for-each select="$vNodes[not(position() > 40)]">
      <xsl:value-of select="position()"/>
      <xsl:text>&#xA;</xsl:text>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к любому документу XML (не используется), оно производит числа от 1 до 40 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1 голос
/ 02 января 2012

Сначала совет: обычно такой вопрос указывает на то, что все должно быть сделано по-другому, более в стиле XSLT-esque - например, с помощью шаблона, соответствующего исходному дереву XML и использующего position() для получения индекса текущего узла.

Но если вам нужно, вы можете получить все целые числа от 1 до произвольного числа. Однако, поскольку вы не можете переназначить переменные в XSLT, стандартный способ сделать это - использовать рекурсию:

<xsl:template name="counter">
  <xsl:param name="current"/>
  <xsl:param name="max"/>
  <xsl:if test=" $max >= $current">
    <!-- do whatever you want to do with the current item here -->
    <th><xsl:value-of select="$current"/></th>

    <!-- increase the counter for the recursive call -->
    <xsl:call-template name="counter">
      <xsl:with-param name="current" select="$current + 1"/>
      <xsl:with-param name="max" select="$max"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

Затем вызовите рекурсивный шаблон с начальным значением и вашим максимальным номером:

<xsl:call-template name="counter">
  <xsl:with-param name="current" select="1"/>
  <xsl:with-param name="max" select="$gotten-number"/>
</xsl:call-template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...