xsl-list
[Top] [All Lists]

Re: [xsl] XPath string comparison of two strings representing calendar dates ... any counterexamples?

2017-08-16 11:43:51
On Wed, Aug 16, 2017 at 04:09:15PM -0000, Costello, Roger L. 
costello(_at_)mitre(_dot_)org scripsit:
Note that I am doing mere string comparison. I am comparing the string 
'20170817' against the string '20170816'.

Will the XPath always work? 

If and only if you've got a guarantee that the date format is always
correct.  That strikes me as rash.  (2017817 is going to mess things up,
for example.)  Trusting input isn't a good plan in general and dates
represented in strings in particular.

The below works; I'd be inclined to inclined to do something more
sensible with the date parsing in a production environment.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
xmlns:local="http://www.example.com/local";
    exclude-result-prefixes="xs local" version="2.0">
    <xsl:output method="text" />
    <xsl:variable as="element(Test)" name="input">
        <Test>
            <Date1>20170816</Date1>
            <Date2>20170817</Date2>
        </Test>
    </xsl:variable>
    <xsl:function name="local:error">
        <xsl:message>Something, somewhere, has gone wrong.</xsl:message>
    </xsl:function>
    <xsl:function name="local:makeDate" as="xs:date">
        <xsl:param name="in" as="xs:string" />
        <xsl:choose>
            <xsl:when test="matches($in, 
'^(19|20)[0-9][0-9][01][1-9][0123][1-9]$')">
                <xsl:variable name="year" select="substring($in, 1, 4)" />
                <xsl:variable name="month" select="substring($in, 5, 2)" />
                <xsl:variable name="day" select="substring($in, 7, 2)" />
                <xsl:sequence select="xs:date(concat($year, '-', $month, '-', 
$day))" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:sequence select="local:error()" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>
    <xsl:template match="/">
        <xsl:variable name="date1" as="xs:date*" 
select="local:makeDate($input/Date1)" />
        <xsl:variable name="date2" as="xs:date*" 
select="local:makeDate($input/Date2)" />
        <xsl:choose>
            <xsl:when test="$date1 instance of xs:date and $date2 instance of 
xs:date">
                <xsl:sequence
                    select="
                        if ($date2 gt $date1) then
                            'dates are sequential'
                        else
                            'first date may be after second date'"
                 />
            </xsl:when>
            <xsl:otherwise>
                <xsl:message>Trying to compare non-dates.</xsl:message>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>


-- Graydon
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>