This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
a new(?) grouping problem
- To: xsl-list at mulberrytech dot com
- Subject: a new(?) grouping problem
- From: Mike Brown <mike at skew dot org>
- Date: Wed, 28 Jun 2000 19:02:59 -0600 (MDT)
- Reply-To: xsl-list at mulberrytech dot com
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