xHTML两列表

时间:2015-09-04 04:26:28

标签: xslt

我正在把这头发拉出来,可能是因为我是XSL的新手。我一直在使用JavaScript,但除了一件事,XSL似乎更好地完成了工作。

我想使用table而不是div,因为我需要单元格在给定行上具有相同的高度。我可以使用display:table对div进行此操作,但它确实让我遇到了同样的问题 - 将行放到正确的位置。

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

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

1 个答案:

答案 0 :(得分:0)

由于您没有提供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&amp; 2,3和&amp; 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>