xsl-list
[Top] [All Lists]

Re: Transform list of elements to a sorted and dynamic HTML table

2004-12-12 16:35:37
Interesting and very short solution, although I did not test it.

My "simple" solution (which actually works) looks like this:

<xsl:variable name="Rows">3</xsl:variable>
<xsl:variable name="Columns">4</xsl:variable>

<xsl:template name="item-table">

   <!-- As Michael, I used a variable to manage sorting the items -->

   <xsl:variable name="SortedItems">
       <xsl:for-each select="//items">
           <xsl:sort select="date" order="descending"/>
           <xsl:sort select="name" order="ascending"/>
           <xsl:if test="position() le $Rows * $Columns">
               <xsl:sequence select="."/>
           </xsl:if>
       </xsl:for-each>
   </xsl:variable>

   <!-- I then walk the sorted items by the first one of each row -->

   <xsl:for-each select="$SortedItems/item">
       <xsl:if test="(position() mod $Columns) eq 1">
<xsl:variable name="RowItems" select="following-sibling::node()[position() lt number($Columns)]"/>
           <tr>
               <!-- First Column -->
               <td>
<!-- Add rowspan="$Columns" if there are no other items in this row -->
                   <xsl:if test="not(count($RowItems))">
                       <xsl:attribute name="colspan">
                           <xsl:value-of select="$Columns"/>
                       </xsl:attribute>
                   </xsl:if>
<!-- Insert formatted item data -->
                   <xsl:apply-templates select="." mode="cell-content"/>
               </td>

               <!-- Create other columns in current row -->
<xsl:for-each select="following-sibling::node()[position() lt number($Columns)]">
                  <td>
<!-- If current node is last of current row add colspan=".." attribute --> <xsl:if test="count(following-sibling::node()[position() lt number($Columns)]) eq 0 and
                                    not(position() eq number($Columns)-1)">
                          <xsl:attribute name="colspan">
<xsl:value-of select="number($Columns) - position()"/>
                          </xsl:attribute>
                      </xsl:if>

                      <!-- Insert formatted item data -->
                      <xsl:apply-templates select="." mode="cell-content"/>
                  </td>
               </xsl:for-each>
           </tr>
       </xsl:if>
   </xsl:for-each>

</xsl:template>

<xsl:template match="//item" mode="cell-content">
   <xsl:value-of select="name"/>
</xsl:template>

Probably not the easiest way, but to me it seemed to be the most ovious one.

Any tips, hints, comments, disagreements?

Regards,
Jannis


Michael Kay schrieb:

First sort:

<xsl:variable name="sorted-names" as="element(td)*">
 <xsl:perform-sort select="item">
  <xsl:sort select="date" order="descending"/>
  <td><xsl:sequence select="string(name)"/></td>
 </xsl:perform-sort>
</xsl:variable>


Then group:

<xsl:variable name="last-colspan"
select="$columns - (count($sorted-names) mod $columns) + 1 <xsl:for-each-group select="$sorted-names" group-adjacent="position()-1 idiv $columns">
 <tr>
   <xsl:for-each select="current-group()">
     <xsl:choose>
       <xsl:when test=". is $sorted-names[last()] and $last-colspan ne 1">
         <td colspan="{$last-colspan}">
          <xsl:sequence select="string(.)"/>
         </td>
       <xsl:otherwise>
         <xsl:sequence select="."/>
       </xsl:otherwise>
      </xsl:choose>
   </xsl:for-each>
 </tr>
</xsl:for-each-group>

Not tested.

Michael Kay
http://www.saxonica.com/


-----Original Message-----
From: Jannis Pohlmann [mailto:info(_at_)sten-net(_dot_)de] Sent: 12 December 2004 03:58
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] Transform list of elements to a sorted and dynamic HTML table

Good morning,

I have a list of items, e.g.:

<item>
 <name>Adoreable</name>
 <date>2004-12-11</date>
</item>
<item>
 <name>Adjustable</name>
 <date>2004-12-11</date>
</item>
<item>
 <name>Bulk</name>
 <date>2004-12-10</date>
</item>
<item>
 <name>Condensed</name>
 <date>2004-12-12</date>
</item>
<item>
 <name>Compromise</name>
 <date>2004-11-08</date>
</item>

and I want them to be transformed to a sorted and dynamic (columns and rows adjustable by variables - $Columns and $Rows) HTML table (using recent Version of Saxon and XSLT2.0). The sort element are the <date/>-Elements (descending), so the table output had to look like this ($Columns = 2, $Rows = 2):

<table>
 <tr>
   <td>Condensed</td>
   <td>Adjustable</td>
 </tr>
 <tr>
   <td>Adoreable</td>
   <td>Bulk</td>
 </tr>
 <tr>
   <td colspan="2">Compromise</td>
 </tr>
</table>

If there are not enough items to fill the columns of the last row its last <td> should have a "colspan" attribute in order to satisfy layout requirements. No empty rows should be created (e.g. if there are not enough items to fill all <$Rows> rows).

As you may see there exists a second sort element (<name/>, ascending) in my example
but this is no must-have feature.

An alternative way might be to select the first <$Columns * $Rows> items (sorted descendingly by <date/>, of course) - but I see no solution for this, right now.

Is there a way to handle this problem with the power of XSLT?
Regards,
Jannis


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--




--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



<Prev in Thread] Current Thread [Next in Thread>