2012-03-07 41 views
6

Tengo pocas dificultades para asignar una variable de contador y aumentarla y luego verificar un cierto valor en XSLT. Aquí está mi código:Incrementando y comprobando la variable de contador en 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> 

pero, duerma parecen incrementar mi contador y no salir cuando el contador golpea 3. Cualquier ayuda en esto?

Respuesta

11

'Variables' en XSL son en realidad constantes: no puede cambiar su valor. Este:

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

se acaba de salida el valor del $counter+1

Para hacer bucles que tiene que utilizar la recursividad - por ejemplo:

<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> 

Altough es mejor tratar de evitar bucles - en la mayoría En los casos en que se puede escribir el XSL para evitarlo, no entiendo lo suficiente de lo que está tratando de lograr para darle la solución completa.

7

Tengo el mismo problema. Necesito incrementar el valor en bucle. Entonces, la forma más sencilla era incluir a Saxon y usar ese valor.

si utiliza 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"> 

si utiliza 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"> 

Y después de eso puede simplemente usar la variable sajón:

<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 --> 
+0

Desafortunadamente, Saxon está limitado a XSLT versión 2.0, por lo que no puede utilizar esta solución con la edición gratuita . – Hraban

2

En Si alguien quiere hacer esto mientras usa .net (XslCompiledTransform) puede usar

<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> 

a continuación, agregar una llamada a "customCode: addtocounter()", y luego se podría escribir un mensaje como este <xsl:message><xsl:value-of select="customCode:GetCounter()" /> rows remaining.</xsl:message>

+0

Buena respuesta, acaba de utilizar esto en un mapa xslt para BizTalk – basvo

1

Nos actualización del canto xsl:variable, ya que son como constantes. Pero podemos actualizar dp:local-variables, por lo que aquí el contador dp:local-variable se inicializa antes de iniciar for-loop. Cada bucle vez que se ejecuta contador se actualizará automáticamente en 1. intenta esto:

<?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> 
+0

Parece que el espacio de nombres 'dp' es una referencia a IBM DataPower ... que no tiene ninguna referencia en su hoja. Además, su etiqueta de la hoja de estilo no está cerrada. Incluso si se corrige la etiqueta de la hoja de estilo, supongo que 'dp' no funcionará sin importar el espacio de nombres o sin ejecutar en un dispositivo IBM ...? –

0

Si quieres saber dónde se encuentra en una función para-cada bucle, puede utilizar la posición incorporada().

<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> 
0

En mi caso yo necesitaba total de cajas en el envío, esto ayudó

<xsl:for-each select="ShippingConfirmation/Details/LicensePlates/LicensePlate"> 
      <xsl:if test="position()=last()"> 
       <xsl:value-of select="position()"/> 
      </xsl:if> 
    </xsl:for-each> 
Cuestiones relacionadas