0

このXMLが必要です。

<list columns="3">
  <item>martin</item>
  <item>donald</item>
  <item>whistler</item>
  <item>mother</item>
  <item>carl</item>
  <item>liz</item>
  <item>cosmo</item>
</list>

このように見えるように:

<table>
  <tr>
    <td>martin</td>
    <td>donald</td>
    <td>whistler</td>
  </tr>
  <tr>
    <td>mother</td>
    <td>carl</td>
    <td>liz</td>
  </tr>
  <tr>
    <td>cosmo</td>
    <td></td>
    <td></td>
  </tr>
</table>

の場合columns="4"、次のようになります。

<table>
  <tr>
    <td>martin</td>
    <td>donald</td>
    <td>whistler</td>
    <td>mother</td>
  </tr>
  <tr>
    <td>carl</td>
    <td>liz</td>
    <td>cosmo</td>
    <td></td>
  </tr>
</table>

XSLTファイルがどのように見えるべきかについてのヒントはありますか?私が知る限り、それはある種のループ(再帰?)を必要としますが、もっとエレガントな方法があるかどうかはわかりません。

4

3 に答える 3

8

私がとるアプローチは、各アイテムの position() の「mod」関数を使用して、1 番目、4 番目、7 番目の位置にあるアイテムを一致させることです。

そのような各アイテムを一致させた後、列数に基づいて次の兄弟をループします。

行を完成させるのに十分なアイテムがない可能性がある最後の行には、最後の行にあったアイテムの数に基づいて空のセルを追加するための再帰的なテンプレートがあります。

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

   <!-- Global variable to get column count -->
   <xsl:variable name="columns" select="number(/list/@columns)"/>

   <!-- Match the root node -->
   <xsl:template match="list">
      <table>
         <!-- Match items in the 1st, 4th, 7th positions, etc (or whatever the column variable holds) -->
         <xsl:apply-templates select="item[position() mod $columns = 1]"/>
      </table>
   </xsl:template>

   <xsl:template match="item">
      <tr>
         <!-- Output the current item -->
         <td>
            <xsl:value-of select="."/>
         </td>
         <!-- Output the following items based on the number of required columns -->
         <xsl:for-each select="following-sibling::item[position() &lt; $columns]">
            <td>
               <xsl:value-of select="."/>
            </td>
         </xsl:for-each>
         <!-- Add in any empty cells if numberof following items is not sufficient -->
         <xsl:call-template name="emptycell">
            <xsl:with-param name="cellcounter" select="count(following-sibling::item[position() &lt; $columns]) + 1" />
         </xsl:call-template>
      </tr>
   </xsl:template>

   <!-- Recursive template to add in empty cells when there are not enough items to complete a row -->
   <xsl:template name="emptycell">
      <xsl:param name="cellcounter" />
      <xsl:if test="$cellcounter &lt; $columns">
         <td></td>
         <xsl:call-template name="emptycell">
            <xsl:with-param name="cellcounter" select="$cellcounter + 1" />
         </xsl:call-template>
      </xsl:if>   
   </xsl:template>

</xsl:stylesheet>
于 2009-10-28T09:00:30.160 に答える
0

CSS3列を使用することをお勧めします。仕様はまもなく候補推奨(実装段階の呼び出し)になり、ベンダープレフィックスを付けてGeckoおよびWebKit(Firefox、Safari、Chrome)にすでに実装されています。

コード:

ul { -moz-column-count: 3; -webkit-column-count: 3; }
于 2009-10-28T15:28:39.380 に答える
0

機能しますが、少し見栄えが悪いもの: position() を悪用します。

<xsl:param name="columns">4</xsl:param>
<xsl:template match="list">
  <xsl:variable name="theList" select="."/>
  <xsl:for-each select="//*[position()<(count(item) / $columns)]>
    <xsl:variable name="idx" select="position()"/>
    <tr>
    <xsl:for-each select="//*[position()<$columns]">
       <td><xsl:value-of select="$theList/item[position() + $idx * $columns]"/></td>
    </xsl:for-each>
    </tr>
  </xsl:for-each>
</xsl:template>

他にも方法があります。たとえば、最初にリスト内の列によって残り 0 で除算されるすべてのノードを選択し、次にそれらの上を歩きます。

上記の手法の詳しい説明については、http://www.ibm.com/developerworks/library/x-tipnodst.htmlを参照してください。

于 2009-10-27T23:31:50.523 に答える