在xsl中动态渲染td

时间:2016-03-02 07:05:09

标签: html xslt

我是xsl的新手,我想根据传入的数据动态渲染td。以下是我用来渲染行和列(固定)的代码。但我不希望以这种方式呈现表格。我希望表格连续渲染为3列,如果有更多数据,它应该创建一个新行并根据动态数据填充td。下面的代码打印带有动态行的新表。我想打印动态列或行,如果3列耗尽,则应创建新行。

<div style="margin:0 auto;">
        <div style="width:730px; margin:0 auto;">
          <h1 style="height:20px;font:normal 18px Calibri;color:#010101;font-weight:600;border-collapse: collapse; margin-left:20px">
            Related Links
          </h1>
          <div style="width:730px; margin:0 auto;">
          <xsl:for-each select="UserResult/ActivityResults/ActivityResult">
          <xsl:if test="ActivityNameForDisplay != ''">
          <h2 style="padding-left:23px;">
            <xsl:value-of select="ActivityNameForDisplay"/>
          </h2>
            <table border="1" width="100%" cellpadding="0" cellspacing="0" class="alignTable">
            <xsl:for-each select="Links/RelatedLinks">
                    <tr style="width:100%">     

                    <td style="width:50%">
                      <strong>
                        <xsl:value-of select="LinkName"/> 
                      </strong>
                    </td>
                    <td style="width:50%">
                      <strong>
                       <xsl:variable name="hyperlink"><xsl:value-of select="Url"/></xsl:variable>
                        <a href="{$hyperlink}" target="_blank"><xsl:value-of select="Url"/> </a>
                      </strong>
                    </td>
                     </tr>
                     </xsl:for-each>
            </table>
            </xsl:if>
            </xsl:for-each>
          </div>
        </div>
      </div>

1 个答案:

答案 0 :(得分:1)

这很棘手但可以使用XSLT1。诀窍是对你的数据进行两次传递:

<xsl:for-each select="Links/RelatedLinks[position() mod 3 = 1]">
    <xsl:variable name="pos" select="position()"/>
    <tr>
        <xsl:for-each select="../RelatedLinks[floor((position()-1) div 3) = $pos - 1]">
            <td>
                <!-- Process column cell here -->
            </td>
        </xsl:for-each>
        <!-- we can add empty td elements here to fill out the row -->
    </tr>
</xsl:for-each>

在外部传递中,我们选择每行中的第一个元素。这些是位置超过3的倍数的项目(第一个,第四个,第七个,等等)。对于每个第一项,我们记录位置。请注意,这些将是1,2,3等(行号),因为它位于每行中第一个项的上下文中。

在内循环中,我们再次传递所有项目。现在我们得到一个小于位置除以3 floored(这给我们的值0,0,0,1,1,1,2,2,2等等)。现在我们检查一下,看看它是否与行号相匹配(我们从中减去1以将其强制为0,1,2等)。这为我们提供了该行的所有元素。

这只会添加实际使用的td元素。如果需要填充每一行,请添加使用

指定的空td元素
<xsl:variable name="count" select="count(../RelatedLinks[floor((position()-1) div 3) = $pos - 1])"/>
<xsl:if test="$count &lt; 3">
    <td/>
</xsl:if>
<xsl:if test="$count &lt; 2">
    <td/>
</xsl:if>

这里我们计算行中使用的元素数量并将其存储为变量(以避免必须计算两次)。然后我们检查我们是否少于3个元素。如果是这样,我们添加一个。然后我们检查我们是否少于2.如果是,我们再添加一个(在这种情况下我们已经添加了一个)。我们不需要检查是否添加了任何内容,因为在这种情况下我们不会有一行。

使用 for-each-group 操作在XSLT 2中更容易:

<xsl:for-each-group select="Links/RelatedLinks" group-by="(position() - 1) idiv 3">
    <tr>
        <xsl:for-each select="current-group()">
            <td>
                <!-- Process column cell here -->
            </td>
        </xsl:for-each>
        <!-- we can add empty td elements here to fill out the row -->
    </tr>
</xsl:for-each-group>

这里我们循环遍历组,其中项目所属的组是通过取一个小于其整数除以3的位置来确定的。这给出了0,0,0,1,1,1,2,2的值,2,依此类推。因此,每三个连续项目被放置在同一组中。然后我们可以遍历组来创建单元格。

要添加空的td元素,我们可以使用

<xsl:if test="count(current-group()) &lt; 3">
    <td/>
</xsl:if>
<xsl:if test="count(current-group()) &lt; 2">
    <td/>
</xsl:if>

此处的逻辑类似于XSLT1解决方案,但我们可以在此处使用预构建组。