开发者

XSLT - build multiple (n) html tables of equal size (in this case, 3x3)

Reference Question 1

Reference Question 2

Ok, both of the preceding links go to discussions of how to build cells and rows within tables. I was hoping to find an expanded example that showed how to build multiple TABLES of N-cells each (in this case 9 cells each - 3x3). I have been trying for a while to use the logic from the two examples and about 500 other places on the web but haven't been able to crack the nut. Can someone, perhaps the contributor to the above links, shed some light on how one would build N-tables of 3x3 from a single dataset as opposed to one table of specific rows?

One of the more difficult constraints I'm finding is that each table needs to be of equal size, empty rows/cells need to be filled in to meet the 3x3 size. It would be super awesome if the posted solution not only solved it for 3x3 but explained the theory in such a way a person could walk away understanding how to extrapolate that for building tables of different sizes.

If it helps, the dataset I'm working with is a SharePoint XML result for a Data View Web Part. The structure coming back is /dsQueryResult/Rows/Row/@values. I am grouping by a "featured" flag and reverse ordering by date in the query itself so the data is ordered as it needs to be. The first item is being sliced off for a special display and the rest are being sliced off into these multiple equal sized tables that will serve as grouped displays for an javascript rotator.

Thanks in advance!

EDIT:

After seeing Alejandro's response I went to build it out in my environment (SharePoint Designer, sadly) and got the following result. I changed the pSequence parameter to "/dsQueryResponse/Rows/*" and the table building worked a treat. However, when I printed out the ID and Title of each object I got the following:

<TABLE>
  <TR>
    <TD>35 - Concern for Community</TD>
    <TD>35 - Concern for Community</TD>
    <TD>35 - Concern for Community</TD>
  </TR>
  <TR>
    <TD>35 - Concern for Community</TD>
    <TD>35 - Concern for Community</TD>
    <TD>35 - Concern for Community</TD>
  </TR>
  <TR>
    <TD>35 - Concern for Community</TD>
    <TD>35 - Concern for Community</TD>
    <TD>35 - Concern for Community</TD>
  </TR>
</TABLE>
<TABLE>
  <TR>
    <TD>26 - Tequila Sunset</TD>
    <TD>26 - Tequila Sunset</TD>
    <TD>26 - Tequila Sunset</TD>
  </TR>
  <TR>
    <TD>26 - Tequila Sunset</TD>
    <TD>26 - Tequila Sunset</TD>
    <TD>26 - Tequila Sunset</TD>
  </TR>
  <TR>
    <TD>26 - Tequila Sunset</TD>
    <TD>26 - Tequila Sunset</TD>
    <TD>26 - Tequila Sunset</TD>
  </TR>
</TABLE>
<TABLE>
  <TR>
    <TD>17 - Oil Well Flare</TD>
    <TD>17 - Oil Well Flare</TD>
    <TD>17 - Oil Well Flare</TD>
  </TR>
  <TR>
    <TD>17 - Oil Well Flare</TD>
    <TD>17 - Oil Well Flare</TD>
    <TD>17 - Oil Well Flare</TD>
  </TR>
  <TR>
    <TD>17 - Oil Well Flare</TD>
    <TD>17 - Oil Well Flare</TD>
    <TD>17 - Oil Well Flare</TD>
  </TR>
</TABLE>

Just a note - the items 1-10 were deleted from the aforementioned dataset hence only 3 tables.

EDIT 2:

You're right Alejandro, I should have included my code. The input XML is as follows:

<xml>
  <dsQueryResponse>
    <x:schema></x:schema>
    <Rows>
      <Row Title="Title 1" ID="33" .... />
      <Row Title="Title 2" ID="32" .... />
      <Row Title="Title 3" ID="31" .... />
      <Row Title="Title 4" ID="30" .... />
      <Row Title="Title 5" ID="29" .... />
      <开发者_StackOverflow中文版Row Title="Title 6" ID="28" .... />
      <Row Title="Title 7" ID="27" .... />
      <Row Title="Title 8" ID="24" .... />
      <Row Title="Title 9" ID="20" .... />
      <Row Title="Title 10" ID="19" .... />
      <Row Title="Title 11" ID="17" .... />
      ...
    </Rows>
  </dsQueryResponse>
</xml>

The ID's are not sequential, items have been removed from the DB, they are just there for example but I wanted to ensure I noted the IDs are not sequential as some objects get deleted occasionally from the list. All data is stored as attributes of the "Row" node.

The desired output for the entire page (even though I'm just focused on the table building itself) is:

<ul id="photoTabs" class="tabs">
  <li>Featured Photo</li>
  <li>Archived Photos (26) [COUNT OF ITEMS MINUS 1])</li>
</ul>
<div id="photoPanes" class="panes">
  <div>
    <p class="photoLibraryImageWrapper">
      <strong>[TITLE OF FIRST ITEM]</strong></p>
      <div style="text-align: center">
        <img style="border-bottom: 0px solid; border-left: 0px solid; border-top: 0px solid; border-right: 0px solid" alt="TITLE OF FIRST ITEM" src="SOURCE OF PHOTO"><br>
        <span class="photoLibraryItemCopyright">[PHOTO CREDIT]</span><br>
        <span class="photoLibraryItemCopyright">[PHOTO COURTESY OF]</span>
      </div>
      <div class="photoLibraryImageWrapper">
        <p>[PHOTO DESCRIPTION]</p>
      </div>
      <div>
        <div style="float: left">
          <a class="prev browse left"></a>
        </div>
        <div class="scrollable">
          <div class="items">
           <div>
            <table>
              <tr>
                <td>
                  Title 2
                </td>
                <td>
                  Title 3
                </td>
                <td>
                  Title 4
                </td>
              </tr>
              <tr>
                <td>
                  Title 5
                </td>
                <td>
                  Title 6
                </td>
                <td>
                  Title 7
                </td>
              </tr>
              <tr>
                <td>
                  Title 8
                </td>
                <td>
                  Title 9
                </td>
                <td>
                  Title 10
                </td>
              </tr>
        </table>
       </div>
       <div>
        <table>
            <tr>
              <td>
                Title 11
              </td>
              <td>
                Title 12
              </td>
              <td>
                Title 13
              </td>
            </tr>
            <tr>
              <td>
                Title 14
              </td>
              <td>
                Title 15
              </td>
              <td>
                Title 16
              </td>
            </tr>
            <tr>
              <td>
                Title 17
              </td>
              <td>
                Title 18
              </td>
              <td>
                Title 19
              </td>
            </tr>
        </table>
       </div>
       <div>
         <table>
            <tr>
              <td>
                Title 20
              </td>
              <td>
                Title 21
              </td>
              <td>
                &nbsp;
              </td>
            </tr>
            <tr>
              <td>
                &nbsp;
              </td>
              <td>
                &nbsp;
              </td>
              <td>
                &nbsp;
              </td>
            </tr>
            <tr>
              <td>
                &nbsp;
              </td>
              <td>
                &nbsp;
              </td>
              <td>
                &nbsp;
              </td>
            </tr>
        </table>
      </div>
      </div>
      <div style="float: left">
        <a class="next browse right"></a>
      </div>
    </div>
   </div>

The problem I'm having is, when I input Alejandro's (ninja-esque) solution I get each table being populated with the first item of the entire set destined to be in the table. So rather than 9 unique cells per table, I'm getting 9 cells of identical values per table. I replaced the $pSequence / in Alejandro's code with /dsQueryResponse/Rows/* and get the above result (from first Edit) where a single item is populating each table.

And anyone who is waiting for me accept Alejandro's solution - don't worry, he will be getting some serious +1's from me for this one, just waiting until the solution is wrapped up. :)


Update: Refactored

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pRows" select="3"/>
    <xsl:param name="pColumns" select="3"/>
    <xsl:template match="/" name="tables">
        <xsl:param name="pSequence" select="*/*"/>
        <xsl:variable name="vSize" select="$pRows * $pColumns"/>
        <xsl:for-each select="$pSequence[position() mod $vSize = 1]">
            <xsl:variable name="vPosition" select="position()"/>
            <table>
                <xsl:call-template name="rows">
                    <xsl:with-param name="pSequence"
                         select="$pSequence[
                                    position() > ($vPosition - 1) * $vSize
                                     and
                                    $vPosition * $vSize + 1 > position()
                                 ]"/>
                </xsl:call-template>
            </table>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="rows">
        <xsl:param name="pSequence" select="/.."/>
        <xsl:param name="pRow" select="$pRows"/>
        <xsl:if test="$pRow">
            <xsl:call-template name="rows">
                <xsl:with-param name="pSequence" select="$pSequence"/>
                <xsl:with-param name="pRow" select="$pRow - 1"/>
            </xsl:call-template>
            <tr>
                <xsl:call-template name="columns">
                    <xsl:with-param name="pSequence"
                         select="$pSequence[
                                    position() > ($pRow - 1) * $pColumns
                                     and
                                    $pRow * $pColumns + 1 > position()
                                 ]"/>
                </xsl:call-template>
            </tr>
        </xsl:if>
    </xsl:template>
    <xsl:template name="columns">
        <xsl:param name="pSequence" select="/.."/>
        <xsl:param name="pColumn" select="$pColumns"/>
        <xsl:if test="$pColumn">
            <xsl:call-template name="columns">
                <xsl:with-param name="pSequence" select="$pSequence"/>
                <xsl:with-param name="pColumn" select="$pColumn - 1"/>
            </xsl:call-template>
            <td>
                <xsl:apply-templates select="$pSequence[$pColumn]"/>
            </td>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Input:

<root>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
    <item>6</item>
    <item>7</item>
    <item>8</item>
    <item>9</item>
    <item>10</item>
    <item>11</item>
    <item>12</item>
    <item>13</item>
    <item>14</item>
    <item>15</item>
    <item>16</item>
</root>

Output:

<table>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td>4</td>
        <td>5</td>
        <td>6</td>
    </tr>
    <tr>
        <td>7</td>
        <td>8</td>
        <td>9</td>
    </tr>
</table>
<table>
    <tr>
        <td>10</td>
        <td>11</td>
        <td>12</td>
    </tr>
    <tr>
        <td>13</td>
        <td>14</td>
        <td>15</td>
    </tr>
    <tr>
        <td>16</td>
        <td></td>
        <td></td>
    </tr>
</table>

Note: It looks like is following a pattern... I might be missing something. I'll revisite this.

EDIT: This stylesheet importing the former (just to show that there are no modifications)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:import href="table.xsl"/>
    <xsl:output method="html"/>
    <xsl:template match="/">
        <xsl:call-template name="tables">
            <xsl:with-param name="pSequence"
                 select="xml/dsQueryResponse/Rows/Row[position()!=1]"/>
        </xsl:call-template>
    </xsl:template>
    <xsl:template match="Row">
        <xsl:value-of select="@Title"/>
    </xsl:template>
</xsl:stylesheet>

With this input:

<xml>
    <dsQueryResponse>
        <x:schema xmlns:x="x"></x:schema>
        <Rows>
            <Row Title="Title 1" ID="33"/>
            <Row Title="Title 2" ID="32"/>
            <Row Title="Title 3" ID="31"/>
            <Row Title="Title 4" ID="30"/>
            <Row Title="Title 5" ID="29"/>
            <Row Title="Title 6" ID="28"/>
            <Row Title="Title 7" ID="27"/>
            <Row Title="Title 8" ID="24"/>
            <Row Title="Title 9" ID="20"/>
            <Row Title="Title 10" ID="19"/>
            <Row Title="Title 11" ID="17"/>
            <Row Title="Title 12" ID="132"/>
            <Row Title="Title 13" ID="131"/>
            <Row Title="Title 14" ID="130"/>
            <Row Title="Title 15" ID="129"/>
            <Row Title="Title 16" ID="128"/>
            <Row Title="Title 17" ID="127"/>
            <Row Title="Title 18" ID="124"/>
            <Row Title="Title 19" ID="120"/>
            <Row Title="Title 20" ID="119"/>
            <Row Title="Title 21" ID="117"/>
        </Rows>
    </dsQueryResponse>
</xml>

Output:

<table>
   <tr>
      <td>Title 2</td>
      <td>Title 3</td>
      <td>Title 4</td>
   </tr>
   <tr>
      <td>Title 5</td>
      <td>Title 6</td>
      <td>Title 7</td>
   </tr>
   <tr>
      <td>Title 8</td>
      <td>Title 9</td>
      <td>Title 10</td>
   </tr>
</table>
<table>
   <tr>
      <td>Title 11</td>
      <td>Title 12</td>
      <td>Title 13</td>
   </tr>
   <tr>
      <td>Title 14</td>
      <td>Title 15</td>
      <td>Title 16</td>
   </tr>
   <tr>
      <td>Title 17</td>
      <td>Title 18</td>
      <td>Title 19</td>
   </tr>
</table>
<table>
   <tr>
      <td>Title 20</td>
      <td>Title 21</td>
      <td></td>
   </tr>
   <tr>
      <td></td>
      <td></td>
      <td></td>
   </tr>
   <tr>
      <td></td>
      <td></td>
      <td></td>
   </tr>
</table>

Note: Using xsl:apply-templates is more flexible than xsl:value-of.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜