Sure, you can rewrite this logic using template rules something like this:
<xsl:template match="Channel">
<h2 class="channel"><xsl:value-of select="Name" /></h2>
<xsl:apply-templates select="Program"/>
</xsl:template>
<xsl:template match="Program">
<div>
<p>
<span class="date">
<xsl:value-of select="Start" />
</span><br />
<span class="title">
<xsl:value-of select="Series" />
</span><br />
<xsl:value-of select="Description" />
</p>
<xsl:apply-templates select="CastList"/>
</div>
</xsl:template>
<xsl:template match="CastList">[list]
<xsl:apply-templates select="CastMember"/>
</ul>
</xsl:template>
<xsl:template match="CastList[not(CastMember)]"/>
<xsl:template match="CastMember">
<li>
<span class="character">
<xsl:value-of select="Character" />
</span>
<span class="actor">
<xsl:value-of select="Actor" />
</span>
</li>
</xsl:template>
But there's no need to be religious about avoiding xsl:if and xsl:for-each. It's good to know how to use both styles, and in most cases, you will end up using both in combination.
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference