>it's essentially the same simplified scenario as above,
and it's essentially the same solution: just wrap an xsl:if around the relevant code. I can't quite see where the problem is.
When you do this:
<xsl:call-template name="category">
<xsl:with-param name="categoryname">Clinical Organizations</xsl:with-param>
</xsl:call-template>
<xsl:for-each select="Collection/Content">
<xsl:if test="Html/root/ReferenceCategory = 'Clinical Organizations'">
you obviously need to avoid the call-template on category if there isn't anything in that category.
Incidentally the construct
<xsl:for-each select="X">
<xsl:if test="Y">
...
</xsl:if>
</xsl:for-each>
can always be replaced by
<xsl:for-each select="X[Y]">
...
</xsl:for-each>
The fact that this code appears twice with only one string literal differing suggests some scope for refactoring:
<xsl:call-template name="category">
<xsl:with-param name="categoryname">Clinical Organizations</xsl:with-param>
</xsl:call-template>
<xsl:for-each select="Collection/Content">
<xsl:if test="Html/root/ReferenceCategory = 'Clinical Organizations'">
<xsl:call-template name="display">
<xsl:with-param name="link" select="Html/root/ExternalLink"/>
<xsl:with-param name="title" select="Title"/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
A general observation, you're trying to write this as if template rules and apply-templates didn't exist. That way, you're avoiding one of the most powerful features of the language, some would say its essential core. It's like using Java and avoiding objects.
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference