4

What are the pros and cons of functions vs templates in XSLT?

I want to send a unix-timestamp and get an answer like "today" or "tomorrow" or "next week". Which method is most appropriate for this?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Himmators
  • 14,278
  • 36
  • 132
  • 223

2 Answers2

3

The main reason of choosing an <xsl:function> over a named template is the much greater degree of composability of a function.

It is very easy and convenient to write an <xsl:function> that produces the wanted results:

 <xsl:function name="my:when" as="xs:string">
  <xsl:param name="pDateTime" as="xs:dateTime"/>

  <xsl:sequence select=
  "for $vToday in xs:dateTime(current-date()),
       $vTomorrow in $vToday
                    + xs:dayTimeDuration('P1D'),
       $vDayAfterTomorrow in $vTomorrow
                    + xs:dayTimeDuration('P1D'),
       $vNextWeek in $vToday
                    + 7* xs:dayTimeDuration('P1D'),
       $vNextFortnight in $vNextWeek
                    + 7* xs:dayTimeDuration('P1D')

       return
         if($pDateTime lt $vToday)
           then 'in the Past'
           else if($pDateTime lt $vTomorrow)
             then 'Today'
             else if($pDateTime lt $vDayAfterTomorrow)
              then 'Tomorrow'
             else if($pDateTime lt $vNextWeek)
              then 'This week'
             else if($pDateTime lt $vNextFortnight)
              then 'Next week'
              else 'In the Future'
  "/>
 </xsl:function>

Here is a complete transformation:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xsl:sequence select="my:when(current-dateTime())"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P1D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P2D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P3D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P4D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P5D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P6D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P7D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P8D'))"/>,
  <xsl:sequence select="my:when(current-dateTime()
                               +xs:dayTimeDuration('P9D'))"/>
 </xsl:template>

 <xsl:function name="my:when" as="xs:string">
  <xsl:param name="pDateTime" as="xs:dateTime"/>

  <xsl:sequence select=
  "for $vToday in xs:dateTime(current-date()),
       $vTomorrow in $vToday
                    + xs:dayTimeDuration('P1D'),
       $vDayAfterTomorrow in $vTomorrow
                    + xs:dayTimeDuration('P1D'),
       $vNextWeek in $vToday
                    + 7* xs:dayTimeDuration('P1D'),
       $vNextFortnight in $vNextWeek
                    + 7* xs:dayTimeDuration('P1D')

       return
         if($pDateTime lt $vToday)
           then 'in the Past'
           else if($pDateTime lt $vTomorrow)
             then 'Today'
             else if($pDateTime lt $vDayAfterTomorrow)
              then 'Tomorrow'
             else if($pDateTime lt $vNextWeek)
              then 'This week'
             else if($pDateTime lt $vNextFortnight)
              then 'Next week'
              else 'In the Future'
  "/>
 </xsl:function>
</xsl:stylesheet>

when this transformation is applied (to any document -- not used), the wanted, correct result is produced:

  Today,
  Tomorrow,
  This week,
  This week,
  This week,
  This week,
  This week,
  Next week,
  Next week,
  Next week
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • +1 Good answer. But this is missing the reazon for choosing `xsl:function` over templates. –  Dec 22 '10 at 20:09
  • @Alejandro: Yes, I thought this was obvious. :) Now I edited my answer and its first sentence explains the most pressing reason. – Dimitre Novatchev Dec 22 '10 at 20:15
  • Excellent edit! Remember that most people don't get the declarative paradigm (an even great XSLT developers refuse to consider XSLT as functional language) so the fundamentals notions about function theory (composition, HOF, tail recursion) are not well known. –  Dec 22 '10 at 20:23
1

In this case, an external function is best-suited.

XSLT is best suited for pattern matching and transformation, not computation.

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • @Kristoffer Nolgren - They are specifically selected functions that are implemented by XSLT processors and thus are efficient. You _could_ write anything using XSLT as it is Turing complete, but it won't be pretty, easy or efficient. – Oded Dec 22 '10 at 16:25
  • Such an answer is not well-founded. It is very easy, natural and convenient to write a simple `` that computes the wanted result. – Dimitre Novatchev Dec 22 '10 at 18:14
  • @Oded: You may be interested in getting introduced to XPath 2.0 and XSLT 2.0, so that your understanding of XSLT and its applicability is improved. – Dimitre Novatchev Dec 22 '10 at 19:19
  • @Dimitre - fair point... I admit that I am stuck in XSLT 1.0... Do you have any pointers regarding good books/websites? – Oded Dec 22 '10 at 19:21
  • @Oded: There are two books by Michael Kay on XSLT2.0/XPath 2.0 that I recommend -- they are listed here: http://stackoverflow.com/questions/339930/any-good-xslt-tutorial-book-blog-site-online/341589#341589 – Dimitre Novatchev Dec 22 '10 at 19:53