2010-04-07 1 views
8

Ho una situazione in cui ciclo attraverso una serie di nodi ordinata e applicare un modello su ciascuno dei nodi:Ordinamento di una serie di nodi prima di passare alla xsl: for-each

<div id="contractscontainer"> 
    <xsl:for-each select="document"> 
    <xsl:sort select="content[@name='ClientName']/text()" /> 
    <xsl:apply-templates select="." mode="client-contract" /> 
    </xsl:for-each> 
</div> 

voglio fare qualcosa di speciale con la " prima "5 nodi nel set di nodi e renderli elementi nidificati. Il problema è che devono essere nello stesso ordine come se fossero ordinati (come sono nel ciclo).

Avevo programmato di farlo utilizzando due elementi xsl:for-each, ciascuno con i nodi corretti selezionati dal set. Non posso fare questo, però, perché hanno bisogno di essere ordinati prima posso selezionare il "primo" 5.

Esempio:

<div id="contractscontainer"> 
    <div class="first-five"> 
    <xsl:for-each select="document[position() < 6]"> 
     <xsl:sort select="content[@name='ClientName']/text()" /> 
     <xsl:apply-templates select="." mode="client-contract" /> 
    </xsl:for-each> 
    </div> 
    <div class="rest-of-them"> 
    <xsl:for-each select="document[position() > 5]"> 
     <xsl:sort select="content[@name='ClientName']/text()" /> 
     <xsl:apply-templates select="." mode="client-contract" /> 
    </xsl:for-each> 
    </div> 
</div> 

Non credo che questo lavoro perché mi seleziono i nodi in base alla posizione prima di ordinandoli, ma non posso usare xsl:sort al di fuori dello xsl:for-each.

Mi si avvicina in modo errato?

Edit: La mia soluzione attuale è quella di ordinarli e memorizzare il ordinato impostato in un'altra variabile:

<xsl:variable name="sorted-docs"> 
    <xsl:for-each select="document"> 
    <xsl:sort select="content[@name='ClientName']/text()" /> 
    <xsl:copy-of select="." /> 
    </xsl:for-each> 
</xsl:variable> 

Funziona, ma c'è un modo migliore?

+0

Buona domanda (+1). La tua soluzione attuale non è male, ma la variabile xsl: con gli elementi ordinati è di tipo RTF e devi usare la funzione di estensione xxx: node-set() in XSLT 1.0. Vedi la mia soluzione come fare questo senza la necessità di alcuna funzione di estensione. –

+0

Sì, ho finito per fare proprio questo: using exsl: node-set(). Grazie per la tua soluzione! –

risposta

14

Qui è un modo per fare questo in XSLT 1.0 senza la necessità di utilizzare la funzione xxx:node-set() estensione:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/*"> 
    <html> 
    <div class="first-five"> 
    <xsl:apply-templates select="num"> 
     <xsl:sort select="." data-type="number"/> 
     <xsl:with-param name="pStart" select="1"/> 
     <xsl:with-param name="pEnd" select="5"/> 
    </xsl:apply-templates> 
    </div> 
    <div class="rest-of-them"> 
    <xsl:apply-templates select="num"> 
     <xsl:sort select="." data-type="number"/> 
     <xsl:with-param name="pStart" select="6"/> 
    </xsl:apply-templates> 
    </div> 
    </html> 
</xsl:template> 

<xsl:template match="num"> 
    <xsl:param name="pStart"/> 
    <xsl:param name="pEnd" select="999999999999"/> 

    <xsl:if test="position() >= $pStart 
       and 
       not(position() > $pEnd)"> 
    <p><xsl:value-of select="."/></p> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

Quando la trasformazione sopra viene applicato su questo semplice documento XML:

<nums> 
    <num>5</num> 
    <num>3</num> 
    <num>6</num> 
    <num>8</num> 
    <num>4</num> 
    <num>1</num> 
    <num>9</num> 
    <num>2</num> 
    <num>7</num> 
    <num>10</num> 
</nums> 

il risultato desiderato è prodotto:

<html> 
    <div class="first-five"> 
     <p>1</p> 
     <p>2</p> 
     <p>3</p> 
     <p>4</p> 
     <p>5</p> 
    </div> 
    <div class="rest-of-them"> 
     <p>6</p> 
     <p>7</p> 
     <p>8</p> 
     <p>9</p> 
     <p>10</p> 
    </div> 
</html> 
+0

Risolto il mio problema, grazie –