I'm new at XSLT and I have a problem:
I'm trying to create a stylesheet with, as input:
<Events>
<Event datetime="2006-10-13T11:20:00">
<Title>blabla</Title>
<Text>blabla</Text>
</Event>
<Event ....
</Events>
as parameters:
$date ; $num
as output: an XHTML showing the first $num elements whose date is > than $date
In my mind the approach will be to order the elements and do a foreach with a if statement to query the elements with a suitable date ... but I need a variable to store the num of elements selected and exit the cycle... It isn't the case, I know.
Can anyone tell me a more clever approach
Thank you.
.utaal

XSLT - Getting the first N elements.
windypoint
Perfect!
Thank you very much.
.utaal
Thiru_
Hi there,
Couple of points, XSLT v1.0 isn't schema aware so you won't be able to treat @datetime as a date value, which means you won't be able to do date > $date. I've had a search through some XSLT reference and there are no date functions so you might be out of luck there. An option might be to write your own XSLT Extension (or see if one already exists) that lets you compare dates. Someone else hear might have a better idea.
I've done a stylesheet that matches the date values and then returns the top N just to show you how you can go about doing a stylesheet. Hope that is helpful..
< xml version='1.0' encoding='UTF-8' >
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html"/>
<xsl:variable name="N">2</xsl:variable>
<xsl:variable name="D">2006-10-13T11:20:00</xsl:variable>
<xsl:key name="dates" match="/Events/Event" use="@datetime"/>
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="key('dates', $D)">
<xsl:if test="position() <= $N">
<p><xsl:value-of select="."/></p>
</xsl:if>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Ultimate
I've noticed that if I put a schema definition reference in the input XML of a XSLT, the parser ignores the templates definition and writes out the XML tag contents (not the tags themselves) as text.
Why does this happen
Thanks.
.utaal
General Fault
Here's a solution which doesn't need any extension function.
The following transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pNDates" select="3"/>
<xsl:param name="pDate" select="'2006-10-13T00:00:00'"/>
<xsl:variable name="pnumDate" select=
"translate($pDate, '-T:','')"/>
<xsl:template match="/">
<xsl:for-each select=
"/*/*[translate(@datetime,'-T:','') > $pnumDate]">
<xsl:sort select="@datetime"/>
<xsl:if test="$pNDates >= position()">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
When applied against this xml document:
<Events>
<Event datetime="2006-10-15T00:00:00"/>
<Event datetime="2006-10-11T00:00:00"/>
<Event datetime="2006-10-14T00:00:00"/>
<Event datetime="2006-10-13T00:00:00"/>
<Event datetime="2006-10-16T00:00:00"/>
<Event datetime="2006-10-12T00:00:00"/>
</Events>
produces the desired result:<Event datetime="2006-10-14T00:00:00" />
<Event datetime="2006-10-15T00:00:00" />
<Event datetime="2006-10-16T00:00:00" />
Hope this helped.
Dimitre Novatchev.
Dave Waterworth
Thanks,
Anton
lcj
MSXML 4.0 and XslCompiledTransform support the ms:string-compare function, which can be used for comparing dates. Suppose you want to extract the first 3 events happened on or after 2006-10-12T00:00:00. You may use the following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="ms"
>
<xsl:param name="Num" select="3"/>
<xsl:param name="Date" select="'2006-10-12T00:00:00'"/>
<xsl:template match="Events">
<xsl:for-each select="Event[ms:string-compare(@datetime, $Date, 'en') >= 0]">
<xsl:sort select="@datetime" order="ascending"/>
<xsl:if test="position() <= $Num">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Applied to this input file:
<Events>
<Event datetime="2006-10-15T00:00:00"/>
<Event datetime="2006-10-11T00:00:00"/>
<Event datetime="2006-10-14T00:00:00"/>
<Event datetime="2006-10-13T00:00:00"/>
<Event datetime="2006-10-16T00:00:00"/>
<Event datetime="2006-10-12T00:00:00"/>
</Events>
it returns these three events:
<Event datetime="2006-10-12T00:00:00" />
<Event datetime="2006-10-13T00:00:00" />
<Event datetime="2006-10-14T00:00:00" />
Thanks,
Anton