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> </xsl:text>
</xsl:function>
</xsl:stylesheet>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson
jim(_dot_)robinson(_at_)stanford(_dot_)edu
Stanford University HighWire Press http://highwire.stanford.edu/
+1 650 7237294 (Work) +1 650 7259335 (Fax)
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--