xHTML two column table



我对这个问题感到很困惑,可能是因为我是XSL新手。我一直在使用JavaScript,但XSL似乎做得更好,除了一件事。

我想使用table而不是div,因为我需要单元格在给定行上具有相同的高度。我可以做到这一点与div使用display:table,但它真的给我留下了同样的问题-得到行在正确的地方。

Abel提交的工作模板如下:
  <table>
    <tbody>
      <xsl:apply-templates select="club[position() mod 2 = 1]" mode="row" />
    </tbody>
  </table>
    <xsl:template match="club" mode="row">
      <tr>
        <xsl:apply-templates select="self::club | following-sibling::club[1]" mode="cell" />
      </tr>
    </xsl:template>
    <xsl:template match="club" mode="cell">
      <td class="club">
         <xsl:apply-templates select="." mode="content" />
      </td>
      <xsl:apply-templates select="self::club" mode="last" />
    </xsl:template>
    <xsl:template match="club" mode="content">
      <!-- a whole bunch of xsl to format a club -->
    </xsl:template>
    <xsl:template match="club[last()][position() mod 2 = 1]" mode="last">
      <td class="club"></td>
    </xsl:template>
    <xsl:template match="node()" mode="last" />

对于两列表的问题,这是一个很好的解决方案(应该很容易扩展到更多列)。

在我的应用程序中,我删除了"last"的类,因为"club"td有一个我不喜欢的空单元格边框。简单地删除"最后"模板也可以,但留下一行只有一个td,这不符合我的审美(不确定它是否正确xhtml)。

谢谢亚伯。我没有足够的帖子来提升你的回答,但这是一个非常好的工作。

由于没有提供XML输入,因此下面的内容有点像有经验的猜测游戏。您的代码显示了一个mod 2,然后调用clubRow模板,这表明您希望每行中有两个俱乐部元素(这也遵循您的问题标题)。

由于您使用following-sibling,这表明所有俱乐部元素都是彼此的兄弟姐妹。我猜你的源代码看起来像这样:

<clubs>
    <club>Club 1</club>
    <club>Club 2</club>
    <club>Club 3</club>
    <club>Club 4</club>
    <club>Club 5</club>
</clubs>

其中1 &2,3 &4分别在一行中,5有自己的行,最后一个单元格为空(在您的代码中为xsl:otherwise)。

如果你使用XSLT 2.0,我会选择xsl:for-each-group与位置分组,但你没有说任何关于什么版本或什么供应商你正在使用,所以我将保持安全,并使用供应商中立的XSLT 1.0。

在我看来,你的想法总体上是合理的,但正如我在评论中注意到的那样,你混合了上下文项,似乎在命名模板和匹配模板之间不知所措。

尝试如下内容(我使用css来显示效果):

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output indent="yes" />
    <xsl:template match="/clubs">
        <table><tbody>
            <xsl:apply-templates 
                select="club[position() mod 2 = 1]" mode="row" />
        </tbody></table>
    </xsl:template>
    <xsl:template match="club" mode="row">
        <tr>
            <!-- apply current and next club -->
            <xsl:apply-templates 
                select="self::club | following-sibling::club[1]" 
                mode="cell" />
        </tr>
    </xsl:template>
    <xsl:template match="club" mode="cell">
        <td class="club">
            <!-- if you have structured content and further processing, use 
                 apply-templates here instead and add more matching templates 
                 in the mode "cell"  -->
            <xsl:value-of select="." />
        </td>
        <!-- re-apply in case this is the last club -->
        <xsl:apply-templates select="self::club" mode="last" />
    </xsl:template>
    <!-- the last, if and only if it is uneven -->
    <xsl:template match="club[last()][position() mod 2 = 1]" mode="last">
        <td class="club"></td>
    </xsl:template>
    <!-- ignore other clubs that are not last -->
    <xsl:template match="node()" mode="last" />
</xsl:stylesheet>

对于给定的输入,这将产生以下内容:

table {
  width: 400px;
  border: 2px solid lightblue;
}
td {
  border: 1px dotted blue;
}
td.club {
  padding: .5em;
  font-family: arial, helvetica, sans-serif;
  font-weight: bold;
}
td:empty {
  background-color: lightblue;
}
<table><tbody>
<tr>
  <td class="club">Club 1</td>
  <td class="club">Club 2</td>
</tr>
<tr>
  <td class="club">Club 3</td>
  <td class="club">Club 4</td>
</tr>
<tr>
  <td class="club">Club 5</td>
  <td class="club" ></td>
</tr>
</tbody></table>

最新更新