Re: [xsl] Getting the first and last nodes of a sorted nodeset

Subject: Re: [xsl] Getting the first and last nodes of a sorted nodeset
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 08 Apr 2004 11:56:25 -0400
John,

Having just posted, I should add:

A friend of mine is trying to get a sorted list of dates and generate output for
all dates from the first to the last (whether they appear in the original XML or not) via a named template which can take a start date and a stop date and generate output for all the dates from start to stop.

This stated requirement doesn't look to me like it should be so hard in principle, so what I described as option 1 (pure XSLT 1.0 solution) should be manageable. Accomplishing it might require inverting your description of the problem: instead of "get[ting] a sorted list of dates and generating output for all dates from the first to last", think of getting an unsorted list of dates and a pair of dates (first and last), and reporting all dates you have that fall between the first and last, and sorting them.


Or perhaps I should be reading more deeply into your hint "whether they appear in the original XML or not". Are you actually asking for how to generate a list of dates *from scratch*, in order, given only a start point and an end point? This is also doable in XSLT 1.0, though it would have to use a couple of advanced methods (specifically you may need one or more recursive templates).

Please clarify.

Cheers,
Wendell

At 11:10 AM 4/8/2004, you wrote:
Hi John,

Since XSLT 1.0 works over the source document, and does not have access to the results of transformation (including sorting), this kind of problem is just plain hard in the 1.0 version of the language.

There are basically three options that I can think of, each of which have different strengths and involve different tradeoffs:

1. Sometimes if the sorting logic is not too complex, it is possible to write it into node selection in more than one place, and/or pass nodes around as parameters, to achieve the desired result. In your case, this would mean not calling a template "where the two parameters are the first and last nodes in a sorted nodeset", but rather where the two parameters are the nodes that *will be* first and last when the set is sorted. This is not the cleanest approach, and sometimes it's not even reasonable. But where it's possible, it keeps to classic 1.0 logic and can be executed by any XSLT processor in one pass.

2. It's not uncommon when doing serious work to pipeline transformations, which makes this kind of thing much easier. The sort is performed in the first pass; the second pass then has access to the sorted order in its "original" source tree. This approach requires you use one of several ways to pipeline transformations together, which of course has implications for your processing architecture (it may be easy or may be hard).

3. Using the XSLT 1.0 extension node-set(), or XSLT 2.0 which includes the node-set() functionality in its processing model, the two passes can be executed in a single run of a single stylesheet. Bind the result of your sort to a variable, turn the variable into a node-set using the node-set() function (look up "Result Tree Fragment" to learn about the 1.0 restriction that makes this necessary) -- or, if running 2.0, don't bother since it's already a node set -- and then process it as if it were input.

Tell us which of these approaches is most reasonable to you and we can look at it again. (In this case, please provide desired output along with some accounting of the logic.) Or maybe an intrepid XSLTer has already looked harder at your code, and can jump in with more specifics. Or maybe you'll just be able to take this and run with it.

Cheers,
Wendell

At 01:07 PM 4/7/2004, you wrote:
Is it possible in XSLT to call a template one time where the 2
parameters are the first and last nodes in a sorted nodeset?  A friend
of mine is trying to get a sorted list of dates and generate output for
all dates from the first to the last (whether they appear in the
original XML or not) via a named template which can take a start date
and a stop date and generate output for all the dates from start to
stop.  I can't think of any way to do it.

<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<root>
 <test>
   <nd>2003-12-31</nd>
   <nd>2004-01-01</nd>
   <nd>2004-01-02</nd>
   <nd>2004-01-03</nd>
   <nd>2004-01-04</nd>
   <test>
     <nd>2004-01-06</nd>
     <nd>2004-01-03</nd>
     <nd>2004-03-01</nd>
   </test>
 </test>
 <test>
   <nd>2004-02-08</nd>
   <nd>2004-01-02</nd>
   <nd>2004-02-03</nd>
   <nd>2004-01-04</nd>
   <nd>2004-02-08</nd>
 </test>
</root>

<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
version='1.0'>
<xsl:output method='html'/>

<xsl:key name='nd_key' match='nd' use='.'/>

<xsl:template match="/root">
<html>
<xsl:for-each
select="//nd[generate-id()=generate-id(key('nd_key',.)[1])]">
  <xsl:sort select="."/>
    <xsl:value-of select="."/><br/>

  <xsl:if test="position()=last()">
    <xsl:call-template name="test_template">
      <!-- first element ?? What to replace select="." with ?? -->
      <xsl:with-param name="b"><xsl:value-of
select="."/></xsl:with-param>
      <!-- last element -->
      <xsl:with-param name="c"><xsl:value-of
select="."/></xsl:with-param>
    </xsl:call-template>
  </xsl:if>

</xsl:for-each>
</html>
</xsl:template>

<xsl:template name="test_template">
  <xsl:param name="b"></xsl:param>
  <xsl:param name="c"></xsl:param>
  <xsl:value-of select="$b" />
  <xsl:value-of select="$c" />
</xsl:template>

</xsl:stylesheet>


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================

Current Thread