I tend to tackle this kind of problem by applying templates only to elements and not to attributes (no real reason, just personal preference). That makes it:
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*[.!='']"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[.=''][not(@*[.!=''])]"/>
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference