a new(?) grouping problem

Subject: a new(?) grouping problem
From: Mike Brown <mike@xxxxxxxx>
Date: Wed, 28 Jun 2000 19:02:59 -0600 (MDT)
Here's what I want to do, with pure XSLT and no xt:node-set or saxon:group
voodoo. Given this XML:

<?xml version="1.0"?>
<Hours>
	<Monday>8am-8pm</Monday>
	<Tuesday>9am-9pm</Tuesday>
	<Wednesday>9am-9pm</Wednesday>
	<Thursday>9am-9pm</Thursday>
	<Friday>8am-8pm</Friday>
	<Saturday>CLOSED</Saturday>
	<Sunday>CLOSED</Sunday>
	<Holidays>CLOSED</Holidays>
</Hours>

I want to group consecutive days with the same hours together, and just
print the first and last day in each group.

I also want to ignore the 'Holidays' day. I put it in there because I
can't use a solution that assumes Sunday's hours aren't followed by
something that could be the same.

The desired output would look like:

<table>
  <tr>
    <td>Monday</td>
    <td>8am-8pm</td>
  </tr>
  <tr>
    <td>Tuesday-Thursday</td>
    <td>9am-9pm</td>
  </tr>
  <tr>
    <td>Friday</td>
    <td>8am-8pm</td>
  </tr>
  <tr>
    <td>Saturday-Sunday</td>
    <td>CLOSED</td>
  </tr>
</table>

It's easy to decide when to create a new row and what the first or only
day listed in it, and the hours, should be. Just iterate through each
non-Holidays day that has hours different than its first preceding
sibling's.

It's also not too difficult to know that a hyphen is needed only when the
first following sibling has the same hours as the current day. Due to the
'Holidays' caveat, this test also has to include a restriction that the
current day isn't Sunday.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">
  <xsl:output method="html" version="4.0"/>
    <xsl:template match="/">
      <xsl:variable name="HoursData" select="/Hours/*[not(name()='Holidays']/>
      <table>
        <xsl:for-each select="$HoursData[normalize-space() != normalize-space(preceding-sibling::*[1])">
          <tr>
            <td>
              <xsl:value-of select="name()"/>
                <!-- if current day isn't Sunday, and next day's hours are
                     the same as this day's, print hyphen -->
                <xsl:if test="name() != 'Sunday' and . = following-sibling::*[not(name()='Holidays')][1]">
                  <xsl:text>-</xsl:text>
                  <!-- the question is, what goes here in place of foo? -->
                  <xsl:value-of select="name(foo)"/>
                </xsl:if>
            </td>
            <td>
              <xsl:value-of select="."/>
            </td>
          </tr>
        </xsl:if>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

I just can't figure out how, at point foo above, to select the last day in
the first set of consecutive, identically-valued siblings following the
current day.

Perhaps someone who hasn't been staring at this as long as I have will
have pity on me and take up this challenge.

   - Mike
____________________________________________________________________
Mike J. Brown, software engineer at         My XML/XSL resources:
webb.net in Denver, Colorado, USA           http://www.skew.org/xml/


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


Current Thread