This is my working solution .
Since you did not provide the desired result, this particular one may not be complete for your needs.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/*"> <table> <xsl:call-template name="make-columns"> <xsl:with-param name="nodelist" select="item"/> </xsl:call-template> </table> </xsl:template> <xsl:template name="make-columns"> <xsl:param name="nodelist"/> <xsl:param name="columns-number" select="4"/> <tr> <xsl:apply-templates select="$nodelist[ not(position() > $columns-number) ]"/> </tr> <xsl:if test="count($nodelist) > $columns-number"> <xsl:call-template name="make-columns"> <xsl:with-param name="nodelist" select="$nodelist[ position() > $columns-number ]"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="item"> <td> <xsl:apply-templates/> </td> </xsl:template> </xsl:stylesheet>
Test input:
<items> <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> </items>
Conclusion:
<table> <tr> <td>1</td> <td>2</td> <td>3</td> <td>4</td> </tr> <tr> <td>5</td> <td>6</td> <td>7</td> <td>8</td> </tr> <tr> <td>9</td> <td>10</td> <td>11</td> <td>12</td> </tr> <tr> <td>13</td> <td>14</td> <td>15</td> <td>16</td> </tr> <tr> <td>17</td> <td>18</td> <td>19</td> <td>20</td> </tr> <tr> <td>21</td> <td>22</td> <td>23</td> <td>24</td> </tr> <tr> <td>25</td> <td>26</td> <td>27</td> </tr> </table>
Please note: you can dynamically transfer column numbers.
Additional requirements and changes.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://localhost" exclude-result-prefixes="my"> <xsl:output method="html" indent="yes"/> <my:layout> <td/><td/><td/><td/> <td/><td/><td/><td/> <td/><td/><td/><td/> <td/><td/><td/><td/> </my:layout> <xsl:template match="/*"> <table> <xsl:call-template name="make-columns"> <xsl:with-param name="nodelist" select="item"/> </xsl:call-template> </table> </xsl:template> <xsl:template name="make-columns"> <xsl:param name="nodelist"/> <xsl:param name="columns-number" select="4"/> <tr> <xsl:apply-templates select="$nodelist[ not(position() > $columns-number) ]"/> <xsl:if test="count($nodelist) < $columns-number"> <xsl:copy-of select="document('')/*/my:layout/td[ position() <= $columns-number - count($nodelist) ]"/> </xsl:if> </tr> <xsl:if test="count($nodelist) > $columns-number"> <xsl:call-template name="make-columns"> <xsl:with-param name="nodelist" select="$nodelist[ position() > $columns-number ]"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="item"> <td> <xsl:apply-templates/> </td> </xsl:template> </xsl:stylesheet>
It can be applied to the previous sample or to this compressed XML:
<items> <item>1</item> </items>
The result will be:
<table> <tr> <td>1</td> <td xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://localhost"></td> <td xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://localhost"></td> <td xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://localhost"></td> </tr> </table>
Note:
- Hard-coded data to add items when there are fewer
item items than the number of columns. - Extra hard-wired items if the number of columns is ever changed.
If the number of elements is less than the number of columns, you can simply apply the same predicate and different mode to the item elements.
And the last edit. With a counted cycle.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/*"> <table> <xsl:call-template name="make-columns"> <xsl:with-param name="nodelist" select="item"/> </xsl:call-template> </table> </xsl:template> <xsl:template name="make-columns"> <xsl:param name="nodelist"/> <xsl:param name="columns-number" select="4"/> <tr> <xsl:apply-templates select="$nodelist[ not(position() > $columns-number) ]"/> <xsl:if test="count($nodelist) < $columns-number"> <xsl:call-template name="empty-cells"> <xsl:with-param name="finish" select="$columns-number - count($nodelist)"/> </xsl:call-template> </xsl:if> </tr> <xsl:if test="count($nodelist) > $columns-number"> <xsl:call-template name="make-columns"> <xsl:with-param name="nodelist" select="$nodelist[ position() > $columns-number ]"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="item"> <td> <xsl:apply-templates/> </td> </xsl:template> <xsl:template name="empty-cells"> <xsl:param name="finish"/> <td/> <xsl:if test="not($finish = 1)"> <xsl:call-template name="empty-cells"> <xsl:with-param name="finish" select="$finish - 1"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>