2010-07-27 2 views
24

Я достаточно новичок в xlst и не понимаю, есть ли способ сохранить значение и изменить его позже, например, увеличивая переменную в цикле.Приращение значения в XSLT

Я немного озадачен тем, что не смог изменить значение a после его установки, не имеет для меня смысла, делая его более постоянным.

Например, я хочу сделать что-то вроде этого:

<xsl:variable name="i" select="0" /> 
<xsl:for-each select="data/posts/entry"> 
    <xsl:variable name="i" select="$i + 1" /> 
    <!-- DO SOMETHING --> 
</xsl:for-each> 

Если кто-нибудь может просветить меня, есть ли альтернативный способ сделать это
Благодаря

+0

Спасибо Dimitre, я не понимал, что переменные могут быть повторно использованы в каждом цикле.Моя проблема была намного сложнее, чем пример, который я опубликовал, и я нашел решение с использованием рекурсии, однако я рассмотрю более элегантное решение, используя ваше предложение. – DonutReply

+1

@Oliver. Хотя рекурсия является чем-то универсальным, есть способы заменить рекурсию на итерация. Это приводит к оптимизации - как по времени, так и по пространству - приложениям xslt. –

ответ

28

XSLT является функциональным языком и среди других вещей, это означает, что переменные в XSLT являются неизменный и onc e они были определены, их значение не может быть изменено.

Вот как тот же эффект может быть достигнут в XSLT:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/"> 
    <posts> 
    <xsl:for-each select="data/posts/entry"> 
     <xsl:variable name="i" select="position()" /> 
     <xsl:copy> 
     <xsl:value-of select="concat('$i = ', $i)"/> 
     </xsl:copy> 
    </xsl:for-each> 
    </posts> 
</xsl:template> 
</xsl:stylesheet> 

когда это преобразование применяется на следующий документ XML:

<data> 
<posts> 
    <entry/> 
    <entry/> 
    <entry/> 
    <entry/> 
    <entry/> 
</posts> 
</data> 

результат :

<posts> 
    <entry>$i = 1</entry> 
    <entry>$i = 2</entry> 
    <entry>$i = 3</entry> 
    <entry>$i = 4</entry> 
    <entry>$i = 5</entry> 
</posts> 
1

Я побежал в это сам два года тому назад. Для этого вам нужно использовать рекурсию. Я забыл точный синтаксис, но этот сайт может помочь:

Tip: Loop with recursion in XSLT

Стратегия работает в основном следующим образом: Заменить for цикл с шаблоном «метод». Получил ли он параметр i. Сделайте тело цикла for в методе шаблона. Если i > 0 снова вызовет метод шаблона (рекурсия) с параметром i - 1.

псевдокод:

for i = 0 to 10: 
    print i 

становится:

def printer(i): 
    print i 
    if i < 10: 
     printer(i + 1) 
printer(0) 

Пожалуйста, обратите внимание, что при использовании position() в xsl:for-each (см другие ответы) может быть проще, если все, что вы хотите сделать, это приращение переменной. Используйте описанную здесь рекурсию, если вы хотите более сложный цикл/условие.

5

Вы можете использовать position() функцию:

<xsl:for-each select="data/posts/entry"> 
    <xsl:text> 
    Postion: ' 
    </xsl:text> 
    <xsl:value-of select = "position()" /> 
    <xsl:text> 
    ' 
    </xsl:text> 
    <!-- DO SOMETHING --> 
</xsl:for-each>
Смежные вопросы