Инкремент и проверка переменной счетчика в XSLT - PullRequest
9 голосов
/ 08 марта 2012

У меня нет особых проблем с назначением переменной счетчика и ее увеличением, а затем проверкой определенного значения в XSLT.Вот мой код:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <xsl:variable name="empty_string"/>
    <xsl:variable name="counter" select="0"/>
<xsl:template match="/Collection">
        <xsl:for-each select="Content">
            <xsl:sort select="Html/root/Event/start_date" order="ascending"/>
 <xsl:variable name="isFutureEvent">
                        <xsl:value-of select="syscom:isFutureDate(Html/root/Event/start_date)" />
                    </xsl:variable>

                    <xsl:if test="Html/root/Event != $empty_string">
                        <xsl:if test="$isFutureEvent='true'">
                            <!-- Increment Counter -->
                            <xsl:value-of select="$counter + 1"/>
                            <!-- Test if Counter < 4 -->
                            <xsl:if test="$counter &lt; 3">
                            <div class="media">
                            <!-- Do stuff here -->
                      </div>
                            </xsl:if>  <!-- End if for counter -->  
                        </xsl:if>
                    </xsl:if>
                <!--</xsl:when>-->
            <!--</xsl:choose>-->
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Но, похоже, он не увеличивает мой счетчик и не выходит из него, когда счетчик достигает 3. Любая помощь в этом?

Ответы [ 6 ]

11 голосов
/ 08 марта 2012

«Переменные» в XSL на самом деле являются константами - вы не можете изменить их значение.Это:

<xsl:value-of select="$counter + 1"/> 

просто выведет значение $counter+1

Для создания циклов вы должны использовать рекурсию - например:

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

  <xsl:template name="loop">
    <xsl:param name="i"/>
    <xsl:param name="limit"/>
    <xsl:if test="$i &lt;= $limit">
      <div>
        <xsl:value-of select="$i"/>
      </div>
      <xsl:call-template name="loop">
        <xsl:with-param name="i" select="$i+1"/>
        <xsl:with-param name="limit" select="$limit"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <xsl:template match="/">
    <html>
      <body>
        <xsl:call-template name="loop">
          <xsl:with-param name="i" select="0"/>
          <xsl:with-param name="limit" select="10"/>
        </xsl:call-template>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

хотя это лучшестараться избегать циклов - в большинстве случаев XSL может быть написан, чтобы избежать этого, но я недостаточно понимаю, чего вы пытаетесь достичь, чтобы дать вам полное решение.

8 голосов
/ 04 декабря 2012

У меня такая же проблема. Мне нужно увеличить значение в цикле. Так что самым простым способом было включить Saxon и использовать это значение.

если вы используете Saxon 6.5.5

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
...
xmlns:saxon="http://icl.com/saxon"
extension-element-prefixes="saxon"
version="3.0">

если вы используете Saxon 9.4.0.4

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
...
xmlns:saxon="http://saxon.sf.net/"
extension-element-prefixes="saxon"
version="3.0">

И после этого вы можете просто использовать саксонскую переменную:

<xsl:variable name="counter" select="0" saxon:assignable="yes"/> <!-- declare value -->

<saxon:assign name="counter" select="$counter+1"/> <!-- increment value, you can do it in loop for example-->

<xsl:value-of select="$counter"></xsl:value-of> <!-- print value -->
3 голосов
/ 23 августа 2017

Если вы хотите знать, где вы находитесь в цикле for-each, вы можете использовать встроенную функцию position ().

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/Collection">
        <xsl:for-each select="Content">
            <xsl:if test="position() &lt; 3">
                <!-- Do this for nodes 1, 2 and 3 -->
            </xsl:if>
            <!-- Do this for every node -->
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
2 голосов
/ 04 декабря 2013

В случае, если кто-то захочет сделать это при использовании .net (XslCompiledTransform), вы можете использовать

<xsl:stylesheet ...  xmlns:customCode="urn:customCode">

<msxsl:script language="VB" implements-prefix="customCode">
    <![CDATA[
    private mCounter As Integer
    Public Function AddToCounter() As Boolean
      mCounter += 1
      Return True
    End Function
    Public Function GetCounter() As Integer
      Return mCounter
    End Function
    ]]>
</msxsl:script>

Затем вы добавляете вызов к «customCode: AddToCounter ()», а затем вы можетенапишите подобное сообщение <xsl:message><xsl:value-of select="customCode:GetCounter()" /> rows remaining.</xsl:message>

0 голосов
/ 21 сентября 2017

В моем случае мне нужно было общее количество коробок в отправке, это помогло

    <xsl:for-each select="ShippingConfirmation/Details/LicensePlates/LicensePlate">
            <xsl:if test="position()=last()">
                <xsl:value-of select="position()"/> 
            </xsl:if>
    </xsl:for-each>
0 голосов
/ 23 марта 2016

Мы не можем обновить xsl:variable, так как они похожи на константы.Но мы можем обновить dp:local-variables, поэтому здесь счетчик dp:local-variable инициализируется перед запуском цикла for.Каждый цикл выполнения счетчика будет обновляться на 1. Попробуйте это:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <xsl:variable name="empty_string"/>
    <xsl:template match="/Collection">
        <dp:set-local-variable name="'counter'" value="0"/>
        <xsl:for-each select="Content">
            <dp:set-local-variable name="'counter'" value="dp:local-variable('counter')+1"/>
            <xsl:sort select="Html/root/Event/start_date" order="ascending"/>
            <xsl:variable name="isFutureEvent">
                <xsl:value-of select="syscom:isFutureDate(Html/root/Event/start_date)" />
            </xsl:variable>

            <xsl:if test="Html/root/Event != $empty_string">
                <xsl:if test="$isFutureEvent='true'">

                    <xsl:value-of select="dp:local-variable('counter')"/>
                    <!-- Test if Counter < 4 -->
                    <xsl:if test="dp:local-variable('counter') &lt; 3">
                        <div class="media">
                            <!-- Do stuff here -->
                        </div>
                    </xsl:if>
                    <!-- End if for counter -->  
                </xsl:if>
            </xsl:if>
            <!--</xsl:when>-->
            <!--</xsl:choose>-->
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...