Subject: Date Validation from String
Posted By: iceandrews Post Date: 5/13/2008 12:11:09 PM
I have a template below for checking to see if a string is a valid date.  The idea here I am getting a document containing a list of dates in string values like so.

<DATES>
<DATE1>20080501</DATE1>
<DATE2>20080901</DATE2>
<DATE3>20080112</DATE3>
....................
<DATE42>20081128</DATE42>
</DATES>

I've written an template that will parse this incoming document and tell you if it is a valid string to represent a date in the YYYYMMDD format.  Just so you no the only valid format for my incoming document should be 'YYYYMMDD'.  It cannot contain any white space.  I thought about using 'matches()' or <xsl:analyze-string>, but I thought this worked better.  I just wanted to bounce it off the experts to see if you can spot any major holes.  Thanks for your thoughts.

    
<xsl:template match="DATES/*" mode="YYYYMMDD" >
        <xsl:variable name="FullDate">
            <xsl:value-of select="."/>
        </xsl:variable>
        <xsl:choose>
            <xsl:when test="string-length(.)=8">
                <xsl:variable name="FullDateFormat">
                    <xsl:value-of select="concat(substring($FullDate, 1, 4),'-',substring($FullDate, 5, 2),'-',substring($FullDate, 7, 2))"/>
                </xsl:variable>
                <xsl:value-of select="if ($FullDateFormat castable as xs:date) then (concat(local-name(.),' is VALID')) else (concat(local-name(.), ' ***IS NOT A DATE***'))" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat(local-name(.), ' ***IS NOT A DATE***')" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>


Reply By: Martin Honnen Reply Date: 5/13/2008 12:21:46 PM
The XML with DATE1, DATE2 and so on looks awful to me.
But the XSLT approach using castable as xs:date looks fine to me. There is no need however for the variable FullDate, you could as well use the dot

concat(substring(., 1, 4),'-',substring(., 5, 2),'-',substring(., 7, 2))

the same you do with string-length(.).

--
  Martin Honnen
  Microsoft MVP - XML
Reply By: iceandrews Reply Date: 5/13/2008 12:51:28 PM
Well, the <DATES> XML isn't really what source file looks like.  It is actually a XML file that contains various elements that should be in the YYYYMMDD format.  This template is only going apply for those elements.

I realized that I really didn't need the variable.  I more did it to keep things straight in my head as I worked through the logic.  The '.' doesn't read well in my mind, so I just did that to be explicit with my thoughts.  Thanks.


Reply By: mhkay Reply Date: 5/13/2008 4:49:59 PM
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
Reply By: iceandrews Reply Date: 5/14/2008 7:25:49 AM
quote:
Originally posted by mhkay
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



Thanks!  Having a different perspective is really helping.  I don't think I would've thought of using replace that way.  This is a great community.


Go to topic 17169

Return to index page 1