It's a really bad habit to use
<xsl:variable name="x">
<xsl:value-of select="y"/>
</xsl:variable>
when you could have written
<xsl:variable name="x" select="y"/>
which is much shorter and much faster.
Apart from that, nothing very wrong with your code, except it can be shortened. I think I would have written it as:
<xsl:template match="DATES/*">
<xsl:value-of select="local-name()"/>
<xsl:value-of select="if (replace(., '([0-9]{4})([0-9]{2})([0-9]{2})', '$1-$2-$3') castable as xs:date)
then ' is VALID' else ' ***IS NOT A DATE***'"/>
</xsl:template>
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference