Re: [xsl] Group and compare data

Subject: Re: [xsl] Group and compare data
From: Anton Triest <anton@xxxxxxxx>
Date: Thu, 07 Oct 2004 10:22:17 +0200
Hi Thomas,

Here's an XSLT 1.0 solution:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="/">
<xsl:apply-templates select="//Forhandler[navn]"/>
</xsl:template>
<xsl:template match="Forhandler">
<xsl:text>&#xa;</xsl:text>
<xsl:value-of select="navn"/>
<xsl:text>&#xa;</xsl:text>
<xsl:apply-templates select="*[starts-with(name(),'aabningstider')][1]" mode="recurse"/>
</xsl:template>
<xsl:template match="*" mode="recurse">
<xsl:param name="start-day" select="substring-after(name(),'aabningstider')"/>
<xsl:variable name="this-day" select="substring-after(name(),'aabningstider')"/>
<xsl:variable name="next" select="following-sibling::*[1][starts-with(name(),'aabningstider')]"/>
<xsl:choose>
<xsl:when test="$next and normalize-space(.) = normalize-space($next/.)">
<xsl:apply-templates select="$next" mode="recurse">
<xsl:with-param name="start-day" select="$start-day"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:text> </xsl:text>
<xsl:if test="$start-day != $this-day">
<xsl:value-of select="$start-day"/>
<xsl:text>-</xsl:text>
</xsl:if>
<xsl:value-of select="$this-day"/>
<xsl:text> </xsl:text>
<xsl:value-of select="normalize-space(.)"/>
<xsl:text>&#xa;</xsl:text>
<xsl:apply-templates select="$next" mode="recurse"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>


It's not *that* tedious is it?  :)
Output (after fixing one "17: 30" in the input):

Dealer name
 Man-Fre  7:30 - 17:30
 Loer  10:00 - 14:00
 Soen  Efter aftale

Another dealer
 Man-Tors  07.30 - 17.30
 Fre  07.30 - 16.00
 Loer-Soen  Lukket

Note: if you control the structure of your input file, consider using a single element name
and putting the day names inside an attribute like this:


<aabningstider day="Man">7:30 - 17:30</aabningstider>
<aabningstider day="Tirs">7:30 - 17:30</aabningstider>
...

It makes selecting them quite a bit easier:
"*[starts-with(name(),'aabningstider')][1]" would become "aabningstider[1]"
"substring-after(name(),'aabningstider')" becomes "@day"

Best regards,
Anton


Verakso wrote:


I have som XML that looks like this:

<Forhandler>
	<Forhandler>
		<navn>Dealer name</navn>
		<email>mail@xxxxxxxxx</email>
		<adresse>road 11</adresse>
		<postnr>9999</postnr>
		<by>city</by>
		<telefon>4444444</telefon>
		<aabningstiderMan>7:30 - 17:30</aabningstiderMan>
		<aabningstiderTirs>7:30 - 17: 30</aabningstiderTirs>
		<aabningstiderOns>7:30 - 17:30</aabningstiderOns>
		<aabningstiderTors>7:30 - 17:30</aabningstiderTors>
		<aabningstiderFre>7:30 - 17:30</aabningstiderFre>
		<aabningstiderLoer>10:00 - 14:00</aabningstiderLoer>
		<aabningstiderSoen>Efter aftale</aabningstiderSoen>
	</Forhandler>
	<Forhandler>
		<navn>Another dealer</navn>
		<email>another@xxxxxxxxx</email>
		<adresse>another road</adresse>
		<postnr>5555</postnr>
		<by>big city</by>
		<telefon>5555555</telefon>
		<aabningstiderMan>07.30 - 17.30</aabningstiderMan>
		<aabningstiderTirs>07.30 - 17.30</aabningstiderTirs>
		<aabningstiderOns>07.30 - 17.30</aabningstiderOns>
		<aabningstiderTors>07.30 - 17.30</aabningstiderTors>
		<aabningstiderFre>07.30 - 16.00</aabningstiderFre>
		<aabningstiderLoer>Lukket</aabningstiderLoer>
		<aabningstiderSoen>Lukket</aabningstiderSoen>
	</Forhandler>
</Forhandler>

What I am trying to accomplish is to group the opening hours so they
look more nice.

For the first dealer the result would be:
Mon-Fre 7:30-17:30
Loer 10:00 - 14:00
Soen Efter aftale

For the second dealer the result would be:
Man-Tor 07.30 - 17.30
Fre 07.30 - 16.00
Loer-Soen Lukket

I have tried som xsl-choose loop, but I went sour in the complexity of
variations, what if a dealer have diffent opening hours every day of
the week.

So I thought, there must be at better approach on how to achieve this.
Is the use of keys a better approach, and if so, how?

/Thomas

Current Thread