XSLT1.0/XPath 1.0 Selecting nodes by date range. Is this even possible?
Lets say I have a list of nodes that contain an attribute datetime, and I want to select only the records that occur after $compare-datetime.
<records>
<record @datetime="2010-01-04T16:48:15.501-05:00"/>
<record @datetime="2010-01-03T16:48:15.501-05:00"/>
...etc...
</records>
In xquery to select items within a date range I would do
/records/record[xs:dateTime(@datetime) > xs:dateTime($compare-datetime)]
However in XSLT 1.0 I have tried alot of different approaches and alot of searching for answers, without any luck at getting this to work.
I am beginning to think that short of parsing the actual dateTime to an integer value, this is not a simple task in xslt.
I am hoping someone 开发者_运维百科can give me a definite answer on that so I can at least know what I am up against.
Cheers,
Casey
If the dates will always be in the same time zone, and have fixed-width fields (constant number of digits in each field), I believe you could take this approach: remove punctuation, leaving the numbers, and compare the numbers.
<xsl:variable name="datetime-punctuation" select="'-.:T'" />
<xsl:variable name="stripped-compare-datetime"
select="number(translate($compare-datetime, $datetime-punctuation, ''))" />
Then use
/records/record[number(translate(@datetime, $datetime-punctuation, ''))
> $stripped-compare-datetime)]
May be it's not the best solution, but I have this:
XML input:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="dates.xsl"?>
<records>
<record datetime="2010-01-04T16:48:15.501-05:00"/>
<record datetime="2011-01-04T16:48:15.501-05:00"/>
</records>
XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date">
<xsl:import href="date.difference.template.xsl"/>
<!-- http://exslt.org/date/functions/difference/date.difference.template.xsl -->
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<result1>
<xsl:call-template name="date:difference">
<xsl:with-param name="start" select="record[1]/@datetime"/>
<xsl:with-param name="end" select="'2010-04-04T16:48:15.501-05:00'"/>
</xsl:call-template>
</result1>
<result2>
<xsl:call-template name="date:difference">
<xsl:with-param name="start" select="record[2]/@datetime"/>
<xsl:with-param name="end" select="'2010-04-04T16:48:15.501-05:00'"/>
</xsl:call-template>
</result2>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Result:
<records>
<result1>P90D</result1>
<result2>-P275D</result2>
</records>
Negative difference would mean that first date occurs after the second date.
I am afraid that XSLT 1.0 has no built-in support for dateTimes. It's possible that you may find that someone has written a library - have a look on the XSLT FAQ
See http://www.dpawson.co.uk/xsl/rev2/dates.html#d14938e16 for what XSLT 2.0 can offer.
I had the same problem as you. I built a C# method (so this only works with .Net XSLT):
<msxsl:script language="C#" implements-prefix="user">
<![CDATA[
public bool largerThan(DateTime dt0, DateTime dt1) {
return dt0 > dt1;
}
]]>
</msxsl:script>
with namespaces
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts"
and usage (snippet from my xslt doc)
<xsl:for-each select="../b:post[user:largerThan(@created,$created)]">
精彩评论