2012-09-16 10 views
5
-

Tengo una XSLT como el de abajo, y quiero usar apply-templates dentro del elemento xsl:for-each así que no tengo que repetir el elemento <tr> con las informaciones del "cliente" elemento XML.XSLT apply-templates dentro de cada

Estoy intentando pero sin éxito crear un xsl:template y poner xsl:apply-templates dentro del xsl:for-each.

Sé que puedo usar xsl:call-template, pero ¿hay alguna forma de usar xsl:apply-templates dentro o fuera del for-each?

¿Alguna idea de cómo hacer esto?

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <html> 
     <head><title>Informações</title></head> 
     <body> 
      <h1>Relação de Clientes</h1> 
      <table border="2"> 
       <tr bgcolor="LightBlue"> 
        <th>Nome</th> 
        <th>Telefone</th> 
        <th>Cidade</th> 
        <th>Estado</th> 
        <th>Crédito</th> 
       </tr> 
       <tr> 
        <th colspan="6" bgcolor="LightPink">Critério usado abaixo: exibir todos os elementos ordenado por nome</th> 
       </tr> 
       <xsl:for-each select="informacoes/cliente"> 
       <xsl:sort select="nome" order="ascending" /> 
        <tr> 
        <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
        <td><xsl:value-of select="telefone"/></td> 
        <td><xsl:value-of select="cidade"/></td> 
        <td><xsl:value-of select="estado"/></td> 
        <td><xsl:value-of select="credito"/></td> 
        </tr> 
       </xsl:for-each> 
       <tr> 
        <th colspan="6" bgcolor="LightCyan"> Critério usado abaixo: exibir os clientes da cidade do Rio de Janeiro</th> 
       </tr> 
       <xsl:for-each select="informacoes/cliente"> 
        <xsl:if test="cidade='Rio de Janeiro'"> 
         <tr> 
         <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
         <td><xsl:value-of select="telefone"/></td> 
         <td><xsl:value-of select="cidade"/></td> 
         <td><xsl:value-of select="estado"/></td> 
         <td><xsl:value-of select="credito"/></td> 
         </tr> 
        </xsl:if> 
       </xsl:for-each> 
       <tr> 
        <th colspan="6" bgcolor="LightYellow"> Critério usado abaixo: exibir os clientes do estado do RJ com ordenado pelo nome; </th> 
       </tr> 
       <xsl:for-each select="informacoes/cliente"> 
       <xsl:sort select="nome" order="ascending" /> 
       <xsl:if test="estado='RJ'"> 
        <tr> 
        <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
        <td><xsl:value-of select="telefone"/></td> 
        <td><xsl:value-of select="cidade"/></td> 
        <td><xsl:value-of select="estado"/></td> 
        <td><xsl:value-of select="credito"/></td> 
        </tr> 
       </xsl:if> 
        </xsl:for-each> 
       <tr> 
        <th colspan="6" bgcolor="LightYellow"> Critério usado abaixo: exibir os clientes com crédito entre 250 e 400, em ordem descendente de crédito) </th> 
       </tr> 
       <xsl:for-each select="informacoes/cliente"> 
       <xsl:sort select="credito" order="descending" /> 
       <xsl:if test="credito&gt;250 and credito&lt;400"> 
        <tr> 
        <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
        <td><xsl:value-of select="telefone"/></td> 
        <td><xsl:value-of select="cidade"/></td> 
        <td><xsl:value-of select="estado"/></td> 
        <td><xsl:value-of select="credito"/></td> 
        </tr> 
       </xsl:if> 
        </xsl:for-each> 
       </table> 
      </body> 
     </html> 
     </xsl:template> 
</xsl:stylesheet> 

Respuesta

7

interior de su xsl:for-each donde está interactuando sobre informacoes/cliente, el nodo de contexto será el cliente elemento actual.

Para apply-templates para el nodo de contexto, puede usar . en su instrucción de selección. Por ejemplo:

<xsl:for-each select="informacoes/cliente"> 
    <xsl:sort select="nome" order="ascending" /> 
    <xsl:apply-templates select="."/> 
</xsl:for-each> 

A continuación, crear plantillas para que coincida con el elemento cliente:

<xsl:template match="informacoes/cliente"> 
    <tr> 
     <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
     <td><xsl:value-of select="telefone"/></td> 
     <td><xsl:value-of select="cidade"/></td> 
     <td><xsl:value-of select="estado"/></td> 
     <td><xsl:value-of select="credito"/></td> 
    </tr> 
</xsl:template> 

También podría eliminar la <xsl:if> pruebas que rodean algunos de sus artículos haciendo referencia al nodo de contexto actual utilizando el self:: eje y luego aplicar los criterios de prueba dentro de un filtro de predicado en el nodo de contexto:

<xsl:for-each select="informacoes/cliente"> 
    <xsl:sort select="nome" order="ascending" /> 
    <xsl:apply-templates select="self::*[estado='RJ']"/> 
    </xsl:for-each> 

La aplicación de estos cambios en su ejemplo de estilo:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <html> 
      <head><title>Informações</title></head> 
      <body> 
       <h1>Relação de Clientes</h1> 
       <table border="2"> 
        <tr bgcolor="LightBlue"> 
         <th>Nome</th> 
         <th>Telefone</th> 
         <th>Cidade</th> 
         <th>Estado</th> 
         <th>Crédito</th> 
        </tr> 
        <tr> 
         <th colspan="6" bgcolor="LightPink">Critério usado abaixo: exibir todos os elementos ordenado por nome</th> 
        </tr> 
        <xsl:for-each select="informacoes/cliente"> 
         <xsl:sort select="nome" order="ascending" /> 
         <xsl:apply-templates select="."/> 
        </xsl:for-each> 
        <tr> 
         <th colspan="6" bgcolor="LightCyan"> Critério usado abaixo: exibir os clientes da cidade do Rio de Janeiro</th> 
        </tr> 
        <xsl:for-each select="informacoes/cliente"> 
         <xsl:apply-templates select="self::*[cidade='Rio de Janeiro']"/> 
        </xsl:for-each> 
        <tr> 
         <th colspan="6" bgcolor="LightYellow"> Critério usado abaixo: exibir os clientes do estado do RJ com ordenado pelo nome; </th> 
        </tr> 
        <xsl:for-each select="informacoes/cliente"> 
         <xsl:sort select="nome" order="ascending" /> 
         <xsl:apply-templates select="self::*[estado='RJ']"/> 
        </xsl:for-each> 
        <tr> 
         <th colspan="6" bgcolor="LightYellow"> Critério usado abaixo: exibir os clientes com crédito entre 250 e 400, em ordem descendente de crédito) </th> 
        </tr> 
        <xsl:for-each select="informacoes/cliente"> 
         <xsl:sort select="credito" order="descending" /> 
         <xsl:apply-templates select="self::*[credito&gt;250 and credito&lt;400]"/> 
        </xsl:for-each> 
       </table> 
      </body> 
     </html> 
    </xsl:template> 

    <xsl:template match="informacoes/cliente"> 
     <tr> 
      <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
      <td><xsl:value-of select="telefone"/></td> 
      <td><xsl:value-of select="cidade"/></td> 
      <td><xsl:value-of select="estado"/></td> 
      <td><xsl:value-of select="credito"/></td> 
     </tr> 
    </xsl:template> 
</xsl:stylesheet> 

Como se ha demostrado en la respuesta de Dimitre Novatchev, se puede simplificar aún más su hoja de estilo mediante la eliminación de las declaraciones xsl:for-each y ajustando sus xsl:apply-templates sentencias de selección; aplicando un xsl:sort dentro de las plantillas de aplicar cuando sea necesario para asegurar que los elementos cliente seleccionados se procesen en el orden deseado.

<xsl:apply-templates select="informacoes/cliente[estado='RJ']"> 
    <xsl:sort select="nome" order="ascending" /> 
</xsl:apply-templates> 
+0

¡Respuesta fantástica, Mads !! Entendí perfectamente bien. ¡Self :: tip también es muy bueno! ¡Gracias de nuevo! – delta

+0

Downvoting this answer, porque aunque funciona y responde la pregunta, usar '' es bastante innecesario, ya que es equivalente a ' '. –

+0

@Michael Kay: punto tomado. Acordé que sería más simple y fácil eliminar el 'xsl: for-each'. Estaba intentando responder a la pregunta de cómo, pero olvidé incluir una sugerencia para una forma mejor y más simple de lograr resultados. –

3

Basta con sustituir:

  <xsl:for-each select="informacoes/cliente"> 
      <xsl:sort select="nome" order="ascending" /> 
       <tr> 
       <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
       <td><xsl:value-of select="telefone"/></td> 
       <td><xsl:value-of select="cidade"/></td> 
       <td><xsl:value-of select="estado"/></td> 
       <td><xsl:value-of select="credito"/></td> 
       </tr> 
      </xsl:for-each> 

Con:

<xsl:apply-templates select="informacoes/cliente"> 
    <xsl:sort select="nome" order="ascending" /> 
</xsl:apply-templates> 

Del mismo modo, reemplace:

  <xsl:for-each select="informacoes/cliente">  
       <xsl:if test="cidade='Rio de Janeiro'">  
        <tr>  
        <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td>  
        <td><xsl:value-of select="telefone"/></td>  
        <td><xsl:value-of select="cidade"/></td>  
        <td><xsl:value-of select="estado"/></td>  
        <td><xsl:value-of select="credito"/></td>  
        </tr>  
       </xsl:if>  
      </xsl:for-each> 

con:

<xsl:apply-templates select="informacoes/cliente[cidade='Rio de Janeiro']"/> 

Del mismo modo, sustituir:

  <xsl:for-each select="informacoes/cliente">   
      <xsl:sort select="nome" order="ascending" />   
      <xsl:if test="estado='RJ'">   
       <tr>   
       <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td>   
       <td><xsl:value-of select="telefone"/></td>   
       <td><xsl:value-of select="cidade"/></td>   
       <td><xsl:value-of select="estado"/></td>   
       <td><xsl:value-of select="credito"/></td>   
       </tr>   
      </xsl:if>   
       </xsl:for-each> 

con:

<xsl:apply-templates select="informacoes/cliente[estado='RJ']"> 
    <xsl:sort select="nome" order="ascending" /> 
</xsl:apply-templates> 

Y finalmente reemplazar:

  <xsl:for-each select="informacoes/cliente">    
      <xsl:sort select="credito" order="descending" />    
      <xsl:if test="credito&gt;250 and credito&lt;400">    
       <tr>    
       <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td>    
       <td><xsl:value-of select="telefone"/></td>    
       <td><xsl:value-of select="cidade"/></td>    
       <td><xsl:value-of select="estado"/></td>    
       <td><xsl:value-of select="credito"/></td>    
       </tr>    
      </xsl:if>    
       </xsl:for-each> 

con:

<xsl:apply-templates select="informacoes/cliente[credito >250 and 400 > credito]"> 
    <xsl:sort select="credito" order="descending" /> 
</xsl:apply-templates> 

A continuación, agregue este simple plantilla de:

<xsl:template match="informacoes/cliente"> 
<tr>    
    <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td>    
    <td><xsl:value-of select="telefone"/></td>    
    <td><xsl:value-of select="cidade"/></td>    
    <td><xsl:value-of select="estado"/></td>    
    <td><xsl:value-of select="credito"/></td>    
</tr>    
</xsl:template> 

Su código XSLT completa se convierte ahora en este:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <html> 
     <head><title>Informações</title></head> 
     <body> 
      <h1>Relação de Clientes</h1> 
      <table border="2"> 
       <tr bgcolor="LightBlue"> 
        <th>Nome</th> 
        <th>Telefone</th> 
        <th>Cidade</th> 
        <th>Estado</th> 
        <th>Crédito</th> 
       </tr> 
       <tr> 
        <th colspan="6" bgcolor="LightPink">Critério usado abaixo: exibir todos os elementos ordenado por nome</th> 
       </tr> 
          <xsl:apply-templates select="informacoes/cliente"> 
           <xsl:sort select="nome" order="ascending" /> 
          </xsl:apply-templates> 
          <tr> 
        <th colspan="6" bgcolor="LightCyan"> Critério usado abaixo: exibir os clientes da cidade do Rio de Janeiro</th> 
       </tr> 
       <xsl:apply-templates select="informacoes/cliente[cidade='Rio de Janeiro']"/> 
       <tr> 
        <th colspan="6" bgcolor="LightYellow"> Critério usado abaixo: exibir os clientes do estado do RJ com ordenado pelo nome; </th> 
       </tr> 
          <xsl:apply-templates select="informacoes/cliente[estado='RJ']"> 
           <xsl:sort select="nome" order="ascending" /> 
          </xsl:apply-templates> 
       <tr> 
        <th colspan="6" bgcolor="LightYellow"> Critério usado abaixo: exibir os clientes com crédito entre 250 e 400, em ordem descendente de crédito) </th> 
       </tr> 
          <xsl:apply-templates select="informacoes/cliente[credito >250 and 400 > credito]"> 
           <xsl:sort select="credito" order="descending" /> 
          </xsl:apply-templates> 
       </table> 
      </body> 
     </html> 
     </xsl:template> 

      <xsl:template match="informacoes/cliente"> 
      <tr> 
       <td bgcolor="LightGreen"><xsl:value-of select="nome"/></td> 
       <td><xsl:value-of select="telefone"/></td> 
       <td><xsl:value-of select="cidade"/></td> 
       <td><xsl:value-of select="estado"/></td> 
       <td><xsl:value-of select="credito"/></td> 
      </tr> 
      </xsl:template> 
</xsl:stylesheet> 
+0

¡También es bueno! No estaba al tanto de la posibilidad de omitir la etiqueta xsl: for-each. Gracias Dimitre! – delta

+2

@ user1676355, De nada. Se recomienda evitar el uso de 'xsl: for-each' (para usar' xsl: apply-templates' en su lugar), y esto es posible en el 99.999% de todos los casos. Solo conozco un caso de uso único donde 'xsl: for-each' es realmente necesario. –

+0

@DimitreNovatchev - Tengo una curiosidad increíble: ¿cuál es el caso de uso en el que estás pensando? – ABach