[xsl] Re: last(): selecting the last one?

Subject: [xsl] Re: last(): selecting the last one?
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Mon, 22 Apr 2002 06:50:35 -0700 (PDT)
> when xml-file contains several elements (information)and they have 
> element which tells the date of input and then there is element that 
> tells the clock time of input and another element called subject.  
> 
> How can I find out which one is the last one and
> then select it's subject elements content? 

The FXSL functional programming library is ideally suited for solving
such problems. Simply use (call) the maximum() function (template),
passing to it your own comparison function, like this:

testMaximumDate.xsl:
-------------------
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:vendor="urn:schemas-microsoft-com:xslt"
 xmlns:MycompareDates="MycompareDates"
 exclude-result-prefixes="xsl MycompareDates vendor"
>
   <xsl:import href="maximum.xsl"/>
   
   <xsl:output omit-xml-declaration="yes"/>
   
   <!-- This transformation must be applied to:
        date-time.xml.xml 
    -->
   
     <MycompareDates:MycompareDates/>

    <xsl:template match="/">
      <xsl:variable name="vCMPFun" 
       select="document('')/*/MycompareDates:*[1]"/>

      <xsl:variable name="vrtfResult">
        <xsl:call-template name="maximum">
          <xsl:with-param name="pList" select="/*/*"/>
          <xsl:with-param name="pCMPFun" select="$vCMPFun"/> 
        </xsl:call-template>
      </xsl:variable>
      
      <xsl:value-of select="vendor:node-set($vrtfResult)/*/subject"/>
    </xsl:template>

    <xsl:template name="MycompareDates" match="MycompareDates:*">
         <xsl:param name="arg1"/>
         <xsl:param name="arg2"/>
         
         <xsl:variable name="vDate1" 
              select="translate($arg1/date, '/', '')"/>
         
         <xsl:variable name="vDate2" 
              select="translate($arg2/date, '/', '')"/>
         
         <xsl:choose>
          <xsl:when test="$vDate1 > $vDate2">1</xsl:when>
          <xsl:when test="$vDate1 = $vDate2">
            <xsl:variable name="vTime1" 
             select="translate($arg1/time, ':APM', '')
                    +
                     120000 * (substring($arg1/time, 9,2)='PM')"/>

            <xsl:variable name="vTime2" 
             select="translate($arg1/time, ':APM', '')
                    +
                     120000 * (substring($arg1/time, 9,2)='PM')"/>
            <xsl:if test="$vTime1 > $vTime2">1</xsl:if>
          </xsl:when>
         </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

When applied on the following source xml document:

date-time.xml:
-------------
<contents>
  <entry>
    <date>2002/02/13</date>
    <time>10:24:11AM</time>
    <subject>Subject1</subject>
  </entry>

  <entry>
    <date>2002/02/11</date>
    <time>10:24:11AM</time>
    <subject>Subject2</subject>
  </entry>

  <entry>
    <date>2002/02/13</date>
    <time>10:24:11PM</time>
    <subject>Subject3</subject>
  </entry>

  <entry>
    <date>2002/02/10</date>
    <time>10:24:11AM</time>
    <subject>Subject4</subject>
  </entry>

  <entry>
    <date>2002/02/15</date>
    <time>10:24:11AM</time>
    <subject>Subject5</subject>
  </entry>

  <entry>
    <date>2002/02/15</date>
    <time>10:24:11PM</time>
    <subject>Subject6</subject>
  </entry>

  <entry>
    <date>2002/02/13</date>
    <time>10:24:11AM</time>
    <subject>Subject7</subject>
  </entry>
</contents>

The result of the transformation is:

Subject6


Another way to find a maximum is to use xsl:sort, but the above
solution has at least two advantages over sorting:

1. Sometimes it is very difficult (if possible at all) to express the
sorting criterion as a single XPath expression. In all such cases it
would be literally impossible to perform the sorting using xsl:sort

2. Finding a maximum through sorting has a time complexity
O(N*log2(N)),
which is greater than the linear complexity of the above algorithm. In
case the maximum is sought over a long list of elements, then the
linear algorithm should be preferred.


Cheers,
Dimitre Novatchev.



__________________________________________________
Do You Yahoo!?
Yahoo! Games - play chess, backgammon, pool and more
http://games.yahoo.com/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread