将元素列表转换为2级嵌套结构

时间:2012-10-10 07:37:29

标签: xslt xslt-1.0

我的输入XML文档是一个简单的项目列表。项目数量是任意的:

<items>
  <item name="item1"/>
  <item name="item2"/>
  <item name="item3"/>
  ...
  <item name="itemX"/>
</items>

现在,我想将此列表拆分为HTML表。行数和列数作为参数值给出:

<xsl:param name="rows"/>
<xsl:param name="cols"/>

如果我们让行为3,而cols为2,则生成的HTML应如下所示:

<table>
  <tr>
    <td>item1</td>
    <td>item2</td>
  </tr>
  <tr>
    <td>item3</td>
    <td>item4</td>
  </tr>
  <tr>
    <td>item5</td>
    <td>item6</td>
  </tr>
</table>

<table>
  <tr>
    <td>item7</td>
    <td>item8</td>
  </tr>
  <tr>
    <td>item9</td>
    <td>item10</td>
  </tr>
  <tr>
    <td>item11</td>
    <td>item12</td>
  </tr>
</table>
...

创建<table>的数量因此为ceil(number_of_items / rows / cols)

我有一个基本的想法如何解决这个问题,但我似乎无法得到最后的调整。以下样式表产生的内容接近我想要的内容,但第4,7,10和13项是重复的。 有没有人对如何做到更好?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:param name="cols" select="2"/>
<xsl:param name="rows" select="3"/>

<xsl:template match="/*">
  <html>
    <head/>
    <body>
      <xsl:apply-templates select="*[position() mod ($cols * $rows) = 1]" mode="table"/>
     </body>
   </html>
</xsl:template>

<xsl:template match="*" mode="table">
    <table border="1" id="{@name}">
        <xsl:apply-templates select="." mode="row"/>
        <xsl:apply-templates select="following-sibling::*[position() &gt; 1 and position() mod $rows = 0]" mode="row"/>
     </table>
</xsl:template>

<xsl:template match="*" mode="row">
    <tr id="{@name}">
       <xsl:apply-templates select="." mode="cell"/>
       <xsl:apply-templates select="following-sibling::*[position() &lt; $cols]" mode="cell"/>
    </tr>
</xsl:template>

<xsl:template match="*" mode="cell">
    <td>
        <xsl:apply-templates select="."/>
    </td>
</xsl:template>

<xsl:template match="item">
    <xsl:value-of select="@name"/>
</xsl:template>

</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

您可以尝试将+1添加到$ cols,如下所示:

<xsl:template match="*" mode="row">
<tr id="{@name}">
   <xsl:apply-templates select="." mode="cell"/>
   <xsl:apply-templates select="following-sibling::*[position() &lt; ($cols +1)]" mode="cell"/>
</tr>
</xsl:template>

对表格模板尝试此操作(您必须限制每个表格的项目数量):

<xsl:template match="*" mode="table">
<xsl:variable name="mypos" select="position()"/>
<table border="1" id="{@name}" test="{$mypos}">
    <xsl:apply-templates select="." mode="row"/>
    <xsl:apply-templates select="following-sibling::*[position() &gt; 1 and position() mod  $rows = 0 and position() &lt; $mypos * ($cols * $rows)]" mode="row"/>
 </table>

答案 1 :(得分:1)

这是一个完整的转型

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

 <xsl:param name="pRows" select="3"/>
 <xsl:param name="pCols" select="2"/>

 <xsl:variable name="vItemsInTable" select="$pRows*$pCols"/>

 <xsl:template match="/*">
       <xsl:apply-templates mode="table"
            select="*[position() mod $vItemsInTable =1]"/>
 </xsl:template>

 <xsl:template match="item" mode="table">
  <table>
   <xsl:apply-templates  mode="row" select=
    "(.|following-sibling::*)
       [not(position() > $vItemsInTable) and position() mod $pCols = 1]">
   </xsl:apply-templates>
  </table>
 </xsl:template>

 <xsl:template match="item" mode="row">
  <tr>
   <xsl:apply-templates select=
     ".|following-sibling::*[not(position() > $pCols -1)]"/>
  </tr>
 </xsl:template>

 <xsl:template match="item">
  <td><xsl:apply-templates select="@name"/></td>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档(提供的转换为更具挑战性):

<items>
    <item name="item1"/>
    <item name="item2"/>
    <item name="item3"/>   ...
    <item name="item4"/>
    <item name="item5"/>
    <item name="item6"/>   ...
    <item name="item7"/>
    <item name="item8"/>
    <item name="item9"/>   ...
    <item name="item10"/>   ...
    <item name="item11"/>   ...
    <item name="item12"/>   ...
    <item name="itemX"/>
</items>

产生了想要的正确结果

<table>
   <tr>
      <td>item1</td>
      <td>item2</td>
   </tr>
   <tr>
      <td>item3</td>
      <td>item4</td>
   </tr>
   <tr>
      <td>item5</td>
      <td>item6</td>
   </tr>
</table>
<table>
   <tr>
      <td>item7</td>
      <td>item8</td>
   </tr>
   <tr>
      <td>item9</td>
      <td>item10</td>
   </tr>
   <tr>
      <td>item11</td>
      <td>item12</td>
   </tr>
</table>
<table>
   <tr>
      <td>itemX</td>
   </tr>
</table>