2012-09-16 62 views
5

我有一个像下面这样的XSLT,并且想要在xsl:for-each元素中使用apply-templates,所以我不必重复带有“cliente”XML元素信息的<tr>元素。XSLT apply-templates for each each

我在尝试但没有成功创建xsl:template并将xsl:apply-templates放在xsl:for-each的内部。

我知道我可以使用xsl:call-template,但在for-each的内部或外部是否有任何方式使用xsl:apply-templates

任何想法如何做到这一点?

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

回答

7

里面你xsl:for-each的你在哪里迭代informacoes/cliente,上下文节点将是当前cliente元素。

为了使apply-templates作为上下文节点,您可以在您的select语句中使用.例如:

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

然后,创建模板来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> 

您还可以通过引用当前上下文节点消除<xsl:if>测试周边部分项目self::轴,然后在上下文节点上的谓词过滤器内应用测试标准:

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

应用这些更改您的例子样式表:

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

正如Dimitre Novatchev的回答证明,你还可以通过消除xsl:for-each报表和调整你的xsl:apply-templates SELECT语句简化你的样式表;根据需要在应用模板内部应用xsl:sort,以确保选定的cliente元素按照所需的顺序进行处理。

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

梦幻般的答案,马兹!我理解得非常好。自我::提示也非常好!再次感谢! – delta

+0

Downvoting这个答案,因为它虽然有效并且回答了问题,但是使用''是非常不必要的,因为它等价于''。 –

+0

@迈克尔凯 - 点了。同意删除'xsl:for-each'会更简单和容易。试图回答这个问题,但忽略了一个更好,更简单的方法来取得成果的建议。 –

3

只需更换

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

随着

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

同样,更换

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

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

同样,更换

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

有:

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

最后更换

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

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

然后添加这个简单的模板

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

您完整的XSLT代码现在变成这个

<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

太好了!我不知道可以省略xsl:for-each标签。谢谢Dimitre! – delta

+2

@ user1676355,不客气。建议避免使用'xsl:for-each'(而不是使用'xsl:apply-templates'),并且这在99.999%的情况下是可能的。我只知道一个用例,其中'xsl:for-each'确实是必需的。 –

+0

@DimitreNovatchev - 我非常好奇:你在想什么? – ABach