Đó là giải pháp làm việc của tôi.
Vì bạn đã không cung cấp kết quả mong muốn, điều này có thể không phù hợp với nhu cầu của bạn.
<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>
<!-- If some nodes are left, recursively call current
template, passing only nodes that are left -->
<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>
Kiểm tra đầu vào:
<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>
Output:
<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>
Do lưu ý: bạn có thể vượt qua cột số tự động.
Yêu cầu bổ sung và chỉnh sửa.
<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>
<!-- If some nodes are left, recursively call current
template, passing only nodes that are left -->
<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>
Nó có thể được áp dụng cho các mẫu trước đó hoặc XML ngắn gọn này:
<items>
<item>1</item>
</items>
Kết quả sẽ là:
<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>
Do lưu ý:
- Dữ liệu được mã hóa cứng để thêm các phần tử, khi có ít hơn
item
phần tử hơn số cột.
- Yếu tố mã hóa bổ sung, nếu số lượng cột sẽ thay đổi.
Nếu không bao giờ có ít thành phần hơn số cột, bạn chỉ có thể áp dụng cho các thành phần item
có cùng vị từ và khác nhau mode
.
Và chỉnh sửa cuối cùng. Với vòng lặp được tính.
<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>
<!-- If some nodes are left, recursively call current
template, passing only nodes that are left -->
<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>
Câu hỏi hay, +1. Xem câu trả lời của tôi cho giải pháp có lẽ ngắn nhất mà thậm chí không sử dụng bất kỳ đệ quy rõ ràng nào. :) –
Đã thêm giải pháp XSLT 2.0. :) –