XSL: список разделен на столбцы - PullRequest
3 голосов
/ 17 марта 2010

помогите мне, пожалуйста. Есть список узлов.

<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» (произвольное число) равными частями.

Если количество узлов не разделено поровну, то пусть последний набор узлов будет содержать остаток от деления.

Например, если входной список содержит 33 элемента, а выходной должен иметь 4 части с равномерно распределенными элементами. На выходе нужно получить 3 части по 9 элементов и одну часть с 6 элементами в сумме 33.

вход * * 1 010

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

выход

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

Разделен на 4 цвета.

Ответы [ 3 ]

5 голосов
/ 17 марта 2010

Это решение не требует, чтобы узлы, сгруппированные в столбцы, были родными :

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

При применении к этому документу 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>

Требуемый результат получен :

<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>
2 голосов
/ 17 марта 2010

Это отдельный ответ на новый вопрос, заданный ОП в одном из его комментариев к принятому ответу:

Большое спасибо, ваш код полностьюза работой.Это так!Тогда еще один вопрос: как можно сначала отсортировать весь список по алфавиту, а затем разделить его на столбцы?- @ kalininew

Это почти так же просто, как и раньше , требуется еще один дополнительный шаг:

  1. Сортировка узлов

  2. Применение функции расширения xxx:node-set() (подсказка: exslt:node-set() реализуется большинством браузеров) для преобразования RTF (Result Tree Fragment), созданного на шаге 1 выше, в обычный набор узлов.

  3. Примените преобразование, решающее исходную проблему, к результату шага 2. выше.

1 голос
/ 17 марта 2010
<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...