2012-09-16 107 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