2010-03-17 5 views
3

aidez-moi s'il vous plaît. Il y a une liste de noeuds.XSL: Liste divisée en colonnes

<list> 
    <item>1</item> 
    <item>2</item> 
    <item>3</item> 
    <item>4</item> 
    <item>5</item> 
    <item>6</item> 
    <item>7</item> 
    and so on... 
</list> 

nécessité de diviser la liste de "n" (nombre arbitraire) à parts égales.

Si le nombre de nœuds n'est pas divisé également, laissez le dernier jeu de nœuds contenir le reste de la division. Par exemple, si la liste d'entrée contient 33 éléments et que la sortie doit comporter 4 parties avec des éléments répartis uniformément. A la sortie pour obtenir 3 à 9 parties d'éléments et une partie de 6 éléments de la somme de 33.

entrée

<ul> 
    <li>1</li> 
    <li>2</li> 
    ... 
    <li>33</li> 
</ul> 

sortie

<ul> 
    <li>1</li> 
    <li>2</li> 
    ... 
    <li>9</li> 
</ul> 
<ul> 
    <li>10</li> 
    <li>11</li> 
    ... 
    <li>18</li> 
</ul> 
<ul> 
    <li>19</li> 
    <li>11</li> 
    ... 
    <li>27</li> 
</ul> 
<ul> 
    <li>28</li> 
    <li>30</li> 
    ... 
    <li>33</li> 
</ul> 

divisé en 4 cols.

+0

Je ne suis pas clair quant à votre sortie désirée. Pouvez-vous le poster aussi sur la base de quelques valeurs d'échantillon de "n". –

+0

Voir la solution que j'ai postée - elle est plus générale et ne nécessite pas que les nœuds soient frères et soeurs. –

Répondre

5

Cette solution ne nécessite pas que les noeuds à être regroupés en colonnes doivent être frères et soeurs:

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

<xsl:variable name="vNodes" select="/*/*/text()"/> 

<xsl:param name="vNumParts" select="4"/> 

<xsl:variable name="vNumCols" select= 
    "ceiling(count($vNodes) div $vNumParts)"/> 

<xsl:template match="/"> 
    <table border="1"> 
    <xsl:for-each select= 
     "$vNodes[position() mod $vNumCols = 1]"> 
     <xsl:variable name="vCurPos" select= 
     "(position()-1)*$vNumCols +1"/> 
     <tr> 
      <xsl:for-each select= 
      "$vNodes[position() >= $vCurPos 
        and 
        not(position() > $vCurPos + $vNumCols -1) 
        ]"> 
      <td><xsl:copy-of select="."/></td> 
      </xsl:for-each> 
     </tr> 
    </xsl:for-each> 
    </table> 
</xsl:template> 
</xsl:stylesheet> 

Lorsqu'il est appliqué sur ce document XML:

<list> 
    <item>1</item> 
    <item>2</item> 
    <item>3</item> 
    <item>4</item> 
    <item>5</item> 
    <item>6</item> 
    <item>7</item> 
    <item>8</item> 
    <item>9</item> 
    <item>10</item> 
    <item>11</item> 
    <item>12</item> 
    <item>13</item> 
    <item>14</item> 
    <item>15</item> 
    <item>16</item> 
    <item>17</item> 
    <item>18</item> 
    <item>19</item> 
    <item>20</item> 
    <item>21</item> 
    <item>22</item> 
    <item>23</item> 
    <item>24</item> 
    <item>25</item> 
    <item>26</item> 
    <item>27</item> 
    <item>28</item> 
    <item>29</item> 
    <item>30</item> 
    <item>31</item> 
    <item>32</item> 
    <item>33</item> 
</list> 

Le résultat désiré est produit:

<table border="1"> 
    <tr> 
     <td>1</td> 
     <td>2</td> 
     <td>3</td> 
     <td>4</td> 
     <td>5</td> 
     <td>6</td> 
     <td>7</td> 
     <td>8</td> 
     <td>9</td> 
    </tr> 
    <tr> 
     <td>10</td> 
     <td>11</td> 
     <td>12</td> 
     <td>13</td> 
     <td>14</td> 
     <td>15</td> 
     <td>16</td> 
     <td>17</td> 
     <td>18</td> 
    </tr> 
    <tr> 
     <td>19</td> 
     <td>20</td> 
     <td>21</td> 
     <td>22</td> 
     <td>23</td> 
     <td>24</td> 
     <td>25</td> 
     <td>26</td> 
     <td>27</td> 
    </tr> 
    <tr> 
     <td>28</td> 
     <td>29</td> 
     <td>30</td> 
     <td>31</td> 
     <td>32</td> 
     <td>33</td> 
    </tr> 
</table> 
+0

Merci beaucoup, votre code fonctionne pleinement. C'est vrai! Puis encore une autre question: comment trier d'abord la liste entière par ordre alphabétique, puis la diviser en colonnes? – Kalinin

+0

@kalininew: Posez cette question comme une nouvelle question et je serai heureux de répondre :) Plus sérieusement, je dois maintenant me préparer à aller au travail - répondra dans probablement 3 heures. –

+0

Merci, j'attendrai une réponse. – Kalinin

1
<xsl:variable name="max" select="4" /> 

<xsl:template match="/"> 
    <xsl:apply-templates select="list" mode="split" /> 
</xsl:template> 

<xsl:template match="list" mode="split"> 
    <xsl:apply-templates select="item[position() mod $max = 1]" mode="split" /> 
</xsl:template> 

<xsl:template match="item" mode="split"> 
    <list> 
    <xsl:copy-of select=". | following-sibling::item[position() &lt; $max]" /> 
    </list> 
</xsl:template> 
+0

Ce n'est pas quelque chose qui devrait être. Vous divisez en groupes de 4 éléments dans le groupe, et vous devez les diviser en 4 groupes, répartis uniformément tous les éléments. – Kalinin

+0

@kalininew: Voulez-vous sérieusement me dire que vous êtes incapable de calculer dynamiquement $ 'max'? Voici un indice 'plafond (count (/ list/item) div 4)' – Tomalak

2

Ceci est une réponse distincte à une nouvelle question posée par l'OP dans un de ses commentaires à la réponse acceptée:

Merci beaucoup, votre code est entièrement fonctionnel. C'est vrai! Puis encore une autre question: comment d'abord trier alphabétiquement la liste entière, puis diviser en colonnes? - @kalininew

C'est presque aussi facile qu'avant, avec une étape supplémentaire nécessaire:

  1. Trier les noeuds

  2. Appliquer la fonction d'extension xxx:node-set() (indice: exslt:node-set() est mis en œuvre par la plupart des navigateurs) pour convertir le RTF (Result Tree Fragment) créé à l'étape 1. ci-dessus en un ensemble de nœuds régulier.

  3. Appliquez la transformation qui résout le problème d'origine, au résultat de l'étape 2. ci-dessus.

+0

Merci, je suis allé essayer. – Kalinin

Questions connexes