用 XSL 生成 HTML 日历[yysun]

XML:

<?xml version="1.0"?>

<page>

<year>2002</year>

<month num="3" start="6" days="31">March, 2002</month>

<day>19</day>

</page>

XSL:

<?xml version="1.0"?>

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

<xsl:variable name="start" select="/page/month/@start"/>

<xsl:variable name="count" select="/page/month/@days"/>

<xsl:variable name="total" select="$start + $count - 1"/>

<xsl:variable name="overflow" select="$total mod 7"/>

<xsl:variable name="nelements">

<xsl:choose>

<xsl:when test="$overflow > 0"><xsl:value-of select="$total + 7 - $overflow"/></xsl:when>

<xsl:otherwise><xsl:value-of select="$total"/></xsl:otherwise>

</xsl:choose>

</xsl:variable>

<xsl:template match="/">

<table bordercolor="#88A5DB" width="100%">

<tr align="center">

<td> </td>

<td><b><xsl:value-of select="/page/month"/></b></td>

<td> </td>

</tr>

</table><br/>

<table bordercolor="#88A5DB" width="100%">

<tr align="center">

<td width="150">Sunday</td>

<td width="150">Monday</td>

<td width="150">Tuesday</td>

<td width="150">Wendsday</td>

<td width="150">Thirsday</td>

<td width="150">Friday</td>

<td width="150">Saturday</td>

</tr>

<xsl:call-template name="month"/>

</table>

</xsl:template>

<!-- Called only once for root -->

<!-- Uses recursion with index + 7 for each week -->

<xsl:template name="month">

<xsl:param name="index" select="1"/>

<xsl:if test="$index < $nelements">

<xsl:call-template name="week">

<xsl:with-param name="index" select="$index"/>

</xsl:call-template>

<xsl:call-template name="month">

<xsl:with-param name="index" select="$index + 7"/>

</xsl:call-template>

</xsl:if>

</xsl:template>

<!-- Called repeatedly by month for each week -->

<xsl:template name="week">

<xsl:param name="index" select="1"/>

<tr height="50" valign="top">

<xsl:call-template name="days">

<xsl:with-param name="index" select="$index"/>

<xsl:with-param name="counter" select="$index + 6"/>

</xsl:call-template>

</tr>

</xsl:template>

<!-- Called by week -->

<!-- Uses recursion with index + 1 for each day-of-week -->

<xsl:template name="days">

<xsl:param name="index" select="1"/>

<xsl:param name="counter" select="1"/>

<xsl:choose>

<xsl:when test="$index < $start">

<td bgcolor="#eeeeee">-</td>

</xsl:when>

<xsl:when test="$index - $start + 1 > $count">

<td bgcolor="#eeeeee">-</td>

</xsl:when>

<xsl:when test="$index > $start - 1">

<td>

<xsl:if test="/page/day[.=($index - $start + 1)]">

<xsl:attribute name="bgcolor">#ffeeee</xsl:attribute>

</xsl:if>

<xsl:value-of select="$index - $start + 1"/>

<xsl:if test="/page/day[.>=($index - $start + 1)]">

<p align="right"><br/></p>

</xsl:if>

</td>

</xsl:when>

</xsl:choose>

<xsl:if test="$counter > $index">

<xsl:call-template name="days">

<xsl:with-param name="index" select="$index + 1"/>

<xsl:with-param name="counter" select="$counter"/>

</xsl:call-template>

</xsl:if>

</xsl:template>

</xsl:stylesheet>

这段 XSL 常常让我想起当年啃 prolog 的情形。当时花了很多时间才搞清楚用递归来实现循环。

XSL 也可以用递归来实现循环。