2008-12-03 47 views
10

¿Cómo guardo las iteraciones que se han producido en un xsl: for-each? (las variables en XSL son inmutables)xsl: para cada contador de bucle

Mi objetivo es encontrar el número MAX de hijos para cualquier nodo en un nivel particular.

Por ejemplo, puede ser que quiera imprimir que no hay más de 2 nodos de respuesta para cualquier pregunta de esta encuesta:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<?xml-stylesheet type="text/xsl" href="testing.xsl"?> 
<Survey> 
    <Question> 
    <Response text="Website" /> 
    <Response text="Print Ad" /> 
    </Question> 
    <Question> 
    <Response text="Yes" /> 
    </Question> 
</Survey> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:template match="/"> 
    <html> 
    <head> 
    </head> 
    <body> 
    <xsl:for-each select="Survey"> 
     The survey has <xsl:value-of select="count(child::Question)"/> questions. 
     <br /> 
     <xsl:variable name="counter">0</xsl:variable> 
     <xsl:for-each select="Question"> 
     <!-- TODO: increment the counter ??????? --> 
     </xsl:for-each> 
     No more than <xsl:value-of select="$counter"/> responses were returned for any question. 
    </xsl:for-each> 
    </body> 
    </html> 
</xsl:template> 
</xsl:stylesheet> 

Respuesta

10

Uno no "guardar las iteraciones que se han producido en un XSL: for-each "porque XSLT is a functional language y las variables son inmutables.

la siguiente transformación encuentra el máximo deseado:

 
<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="maximum"> 
     <xsl:with-param name="pNodes" select="*/Question"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="maximum"> 
     <xsl:param name="pNodes"/> 

     <xsl:variable name="vNumNodes" select="count($pNodes)"/> 

     <xsl:choose> 
     <xsl:when test="$vNumNodes = 1"> 
      <xsl:value-of select="count($pNodes[1]/Response)"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:variable name="vHalf" 
       select="floor($vNumNodes div 2)"/> 

      <xsl:variable name="vMax1"> 
      <xsl:call-template name="maximum"> 
      <xsl:with-param name="pNodes" 
       select="$pNodes[not(position() > $vHalf)]"/> 
      </xsl:call-template> 
      </xsl:variable> 

      <xsl:variable name="vMax2"> 
      <xsl:call-template name="maximum"> 
      <xsl:with-param name="pNodes" 
       select="$pNodes[position() > $vHalf]"/> 
      </xsl:call-template> 
      </xsl:variable> 

      <xsl:value-of select= 
      "$vMax1*($vMax1 >= $vMax2) + $vMax2*($vMax2 > $vMax1)"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

cuando se aplica sobre el documento XML proporcionado:

 
<Survey> 
    <Question> 
     <Response text="Website" /> 
     <Response text="Print Ad" /> 
    </Question> 
    <Question> 
     <Response text="Yes" /> 
    </Question> 
</Survey> 

se produce el resultado deseado:

hacer la nota lo siguiente: La plantilla llamada "maximum" llama a sí mismo de forma recursiva e implementa el DVC (Divide and Conquer principle)para minimizar la profundidad de la pila de recursión. La lista de nodos se divide en dos, los máximos de las dos listas se calculan (recursivamente) y se devuelve el mayor de los dos.

Cuestiones relacionadas