Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Conditional starting and ending of a table row

Status
Not open for further replies.

Jake22

Programmer
Oct 17, 2002
2
US
I am trying to create a calendar display of one month. I am having trouble starting and ending a row based on a condition (using xsl:if). My condition works but it doesn't seem to like not having a starting and ending tag between EACH condition. For example:

<xsl:for-each select=&quot;root/cal&quot;>
<xsl:choose>
<xsl:when test=&quot;@dayofweek='1'&quot;> first day of the week
<tr> start new row with a date in the first element
<td><xsl:value-of select=&quot;@daynumber&quot;/></td>
</xsl:when>
<xsl:eek:therwise>
<tr> start new row with blank first element
<td></td>
</xsl:eek:therwise>
</xsl:choose>

repeat for @daynumber is 2 through 6 without the
starting table row tag


<xsl:choose>
<xsl:when test=&quot;@dayofweek='7'&quot;> last day of the week
<td><xsl:value-of select=&quot;@daynumber&quot;/></td>
</tr> end the row
</xsl:when>
<xsl:eek:therwise>
<td></td>
</tr> end the row
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>

If I add a matching tag between each condition it works but of course does not look like a calendar!

My XML data looks like this:
<root>
<cal dayofweek=&quot;6&quot; daylabel=&quot;1&quot; fulldate=&quot;11/1/2002&quot;/>
<cal dayofweek=&quot;7&quot; daylabel=&quot;2&quot; fulldate=&quot;11/2/2002&quot;/>
<cal dayofweek=&quot;1&quot; daylabel=&quot;3&quot; fulldate=&quot;11/3/2002&quot;/>
<cal ........ etc..... />
</root>
 
XSLT, although a scripting language, also must be valid XML, which is why you have to define whole elements within a <xsl:choose> element. Another way of saying this is that XSLT is a pure functional language.

What you effectively want to do here is group elements - a task which isn't trivial. The best way to achieve this (currently) is using templates and recursion.

I've included a stylesheet below that should give you an idea on how to acheive this. Hope it helps!

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
<xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot; <xsl:eek:utput method=&quot;html&quot; indent=&quot;yes&quot; cdata-section-elements=&quot;script style&quot; doctype-public=&quot;-//W3C//DTD HTML 4.0 Strict//EN&quot;/>
<xsl:template match=&quot;/&quot;>
<xsl:variable name=&quot;day-count&quot; select=&quot;count(root/cal)&quot;/>
<xsl:variable name=&quot;first-dow&quot; select=&quot;root/cal[1]/@dayofweek&quot;/>
<xsl:variable name=&quot;week-count&quot; select=&quot;ceiling(($first-dow - 1 + $day-count) div 7)&quot;/>
<table border=&quot;1&quot;>
<thead>
<tr>
<th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th>
</tr>
</thead>
<tbody>
<xsl:call-template name=&quot;cal-week&quot;>
<xsl:with-param name=&quot;week&quot; select=&quot;1&quot;/>
<xsl:with-param name=&quot;week-count&quot; select=&quot;$week-count&quot;/>
<xsl:with-param name=&quot;day-count&quot; select=&quot;$day-count&quot;/>
<xsl:with-param name=&quot;first-dow&quot; select=&quot;$first-dow&quot;/>
</xsl:call-template>
</tbody>
</table>
</xsl:template>

<xsl:template name=&quot;cal-week&quot;>
<xsl:param name=&quot;week&quot;/>
<xsl:param name=&quot;week-count&quot;/>
<xsl:param name=&quot;day-count&quot;/>
<xsl:param name=&quot;first-dow&quot;/>
<xsl:if test=&quot;$week &lt; ($week-count + 1)&quot;>
<tr>
<xsl:choose>
<xsl:when test=&quot;$week = 1&quot;>
<xsl:call-template name=&quot;cal-pad&quot;>
<xsl:with-param name=&quot;days&quot; select=&quot;$first-dow - 1&quot;/>
</xsl:call-template>
<xsl:call-template name=&quot;cal-days&quot;>
<xsl:with-param name=&quot;day&quot; select=&quot;1&quot;/>
<xsl:with-param name=&quot;day-count&quot; select=&quot;$day-count&quot;/>
<xsl:with-param name=&quot;week-days&quot; select=&quot;8 - $first-dow&quot;/>
</xsl:call-template>
</xsl:when>
<xsl:eek:therwise>
<xsl:call-template name=&quot;cal-days&quot;>
<xsl:with-param name=&quot;day&quot; select=&quot;(($week - 1) * 7) - $first-dow + 2&quot;/>
<xsl:with-param name=&quot;day-count&quot; select=&quot;$day-count&quot;/>
</xsl:call-template>
</xsl:eek:therwise>
</xsl:choose>
<xsl:if test=&quot;$week = $week-count&quot;>
<!-- <xsl:variable name=&quot;last-dow&quot; select=&quot;root/cal[$day-count]/@dayofweek&quot;/> -->
<xsl:variable name=&quot;last-dow&quot; select=&quot;(($first-dow + $day-count - 2) mod 7) + 1&quot;/>
<xsl:call-template name=&quot;cal-pad&quot;>
<xsl:with-param name=&quot;days&quot; select=&quot;7 - $last-dow&quot;/>
</xsl:call-template>
</xsl:if>
</tr>
<xsl:call-template name=&quot;cal-week&quot;>
<xsl:with-param name=&quot;week&quot; select=&quot;$week + 1&quot;/>
<xsl:with-param name=&quot;week-count&quot; select=&quot;$week-count&quot;/>
<xsl:with-param name=&quot;day-count&quot; select=&quot;$day-count&quot;/>
<xsl:with-param name=&quot;first-dow&quot; select=&quot;$first-dow&quot;/>
</xsl:call-template>
</xsl:if>
</xsl:template>

<xsl:template name=&quot;cal-days&quot;>
<xsl:param name=&quot;day&quot;/>
<xsl:param name=&quot;day-count&quot;/>
<xsl:param name=&quot;week-days&quot; select=&quot;7&quot;/>
<xsl:if test=&quot;$day &lt; ($day-count + 1) and $week-days &gt; 0&quot;>
<td><xsl:value-of select=&quot;/root/cal[$day]/@daynumber&quot;/></td>
<xsl:call-template name=&quot;cal-days&quot;>
<xsl:with-param name=&quot;day&quot; select=&quot;$day + 1&quot;/>
<xsl:with-param name=&quot;week-days&quot; select=&quot;$week-days - 1&quot;/>
<xsl:with-param name=&quot;day-count&quot; select=&quot;$day-count&quot;/>
</xsl:call-template>
</xsl:if>
</xsl:template>

<xsl:template name=&quot;cal-pad&quot;>
<xsl:param name=&quot;days&quot;/>
<xsl:if test=&quot;$days &gt; 0&quot;>
<td>&#160;</td>
<xsl:call-template name=&quot;cal-pad&quot;>
<xsl:with-param name=&quot;days&quot; select=&quot;$days - 1&quot;/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
 
Thank you! I really appreciate the time you took to answer my question - your tip was VERY helpful and definitely gives me some new ideas on how to write better XSL. I ended up getting my calendar to work using much less elegant code but am planning to re-write using your tip as a basis. Thanks again!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top