Re: [xsl] dateTime fun

Subject: Re: [xsl] dateTime fun
From: "James A. Robinson" <jim.robinson@xxxxxxxxxxxx>
Date: Wed, 20 Dec 2006 21:59:34 -0800
On Wed, 20 Dec 2006 20:24:29 -0800 I wrote:
< 
< So I'm dealing with a schema which has an attribute:
< 
<   <xs:simpleType  name="time">
<     <xs:union  memberTypes="
<           xs:gYear xs:gYearMonth xs:date xs:dateTime"  />
<   </xs:simpleType>
< 
< I had to write a function to let someone compare two of these 'time'
< simple types.  It appeared as though the only way to do comparisions
< was with equal times, so that mean converting everything to xs:dateTime.

On my walk home I realized I hadn't considered the implication of
just what xs:date, xs:gYearMonth, and xs:gYear actually are -- ranges,
instead of specific points in time.

The details of what I need are:

  'time' may be xs:dateTime, xs:date, xs:gYear, xs:gYearMonth
   $a is a 'time' in a document
   $b is a 'time' provided by a user

   Given $a and $b I want to allow for eq, lt, le, gt, ge
   comparision of $a and $b)

So I came up with the following monster...  It seems like so much
hoop-jumping...  Is there a better way?  Is there a way to do some
sort of immediate check between $a and $b to see if they are
directly comparable?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema";
  xmlns:f="uri.local-functions">
  
  <xsl:output method="text"/>
  
  <xsl:template match="/">
    <xsl:sequence select="f:compare('eq', '2005', '2005-01')"/>
    <xsl:sequence select="f:compare('lt', '2005-01-26', '2009')"/>
    <xsl:sequence select="f:compare('le', '2005', '2005-12-31')"/>
    <xsl:sequence select="f:compare('gt', '2005', '2004-01-19')"/>
    <xsl:sequence select="f:compare('ge', '2005', '2005-12')"/>
    
    <xsl:sequence select="f:compare('eq', '2005', '2007-01')"/>
    <xsl:sequence select="f:compare('lt', '2005-01', '2004')"/>
    <xsl:sequence select="f:compare('le', '2005', '2006-12-31')"/>
    <xsl:sequence select="f:compare('gt', '2008-12-01', '2020-01-19')"/>
    <xsl:sequence select="f:compare('ge', '2005', '2004-12-31')"/>
  </xsl:template>
  
  <xsl:function name="f:convert-to-comparable">
    <xsl:param name="a" as="xs:string"/>
    <xsl:param name="b" as="xs:string"/>

    <xsl:variable name="c" select="
        if ($b castable as xs:dateTime)
        then xs:dateTime($b)
        else if ($b castable as xs:date)
        then xs:dateTime(xs:date($b))
        else if ($b castable as xs:gYearMonth)
        then (xs:dateTime(xs:date(concat(substring($b, 1, 7), '-01', substring($b, 8)))))
        else if ($b castable as xs:gYear)
        then (xs:dateTime(xs:date(concat(substring($b, 1, 4), '-01-01', substring($b, 5)))))
        else ()"/>

    <xsl:sequence select="
        if ($a castable as xs:dateTime)
        then xs:dateTime($a), xs:dateTime($c)
        else if ($a castable as xs:date)
        then xs:date($a), xs:date($c)
        else if ($a castable as xs:gYearMonth)
        then xs:gYearMonth($a), xs:gYearMonth($c)
        else if ($a castable as xs:gYear)
        then xs:gYear($a), xs:gYear($c)
        else ()
      "/>
  </xsl:function>
  
  <xsl:function name="f:compare">
    <xsl:param name="cmp"/>
    <xsl:param name="a"/>
    <xsl:param name="b"/>
    
    <xsl:variable name="c" select="f:convert-to-comparable($a, $b)"/>
  
    <xsl:value-of select="concat($a, ' ', $cmp, ' ', $b, ' = ')"/>
    <xsl:choose>
      <xsl:when test="$cmp eq 'eq'">
        <xsl:sequence select="$c[1] eq $c[2]"/>
      </xsl:when>
      <xsl:when test="$cmp eq 'lt'">
        <xsl:sequence select="$c[1] lt $c[2]"/>
      </xsl:when>
      <xsl:when test="$cmp eq 'le'">
        <xsl:sequence select="$c[1] le $c[2]"/>
      </xsl:when>
      <xsl:when test="$cmp eq 'gt'">
        <xsl:sequence select="$c[1] gt $c[2]"/>
      </xsl:when>
      <xsl:when test="$cmp eq 'ge'">
        <xsl:sequence select="$c[1] ge $c[2]"/>
      </xsl:when>
    </xsl:choose>
    <xsl:text>&#10;</xsl:text>
  </xsl:function>

</xsl:stylesheet>


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson                       jim.robinson@xxxxxxxxxxxx
Stanford University HighWire Press      http://highwire.stanford.edu/
+1 650 7237294 (Work)                   +1 650 7259335 (Fax)

Current Thread