[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] Sorting data after transformation is done


Subject: [xsl] Sorting data after transformation is done
From: "Jean-Yves Avenard" <jyavenard@xxxxxxxxx>
Date: Tue, 29 Apr 2008 23:12:26 +1000

Hello

I am facing a problem that unfortunately, I've been unable to resolve.
For a preamble, I'm very new at XSLT, only started yesterday, so
please forgive my ignorance !

I am working on some xmltv files. An xmltv file (as described in
www.xmltv.org) is a XML file containing TV programme information.
The programme listings look like this:
 <tv>
<programme channel="tpg.aljazeera" start="20080430040000 +0100"
stop="20080430043000 +0100">
   <title>
     Witness
   </title>
   <sub-title>
     Memories of Utopia
   </sub-title>
   <desc>
     Inspirational and provocative stories providing a fresh and
informative insight into the world's key events and their impact on
the lives of ordinary people.
   </desc>
 </programme>
</tv>

As you can see, the programme contains one attribute: start which is a
date in the format YYYYMMDDHHMMSS [+-]XXXX
where XXXX is the timezone.

I have written an XSLT template (I've attached the code below) that
converts that date to UTC as the xmltv file will contain various
programme, all in different timezone depending on the source.

What I'm trying to achieve, is sort the XML file based on the start
attribute, but *after* it has been converted to UTC

Currently, to sort the XML by the start attribute , I would do
something like this:
<xsl:template match="tv">
	<xsl:for-each select="programme">
	<xsl:sort select="@start" order="ascending"/>
		<xsl:value-of select="@start" />
	.	...
	</xsl:for-each>
</xsl:template>

The way I would convert my date, with my template/function is:
	<xsl:variable name="utcstart">
		<xsl:call-template name="UTCDate">
			<xsl:with-param name="DateTime" select="@start"/>
		</xsl:call-template>
	</xsl:variable>

Is this something that would be possible with XSLT?
if not, could you suggest a work around ?

Thank you very much in advance.
Kind regards and all the best

-- My UTC convert template: Unfortunately, I want this to run in my
web browser, and I haven't found one compatible with XSLT 2.0, so I
had to do everything by hand.


	<xsl:template name="DayMonth">
	<xsl:param name="mo" />
	<xsl:param name="year" />
		<xsl:choose>
			<xsl:when test="$mo = 0">31</xsl:when>
			<xsl:when test="$mo = 1">31</xsl:when>
			<xsl:when test="($mo = 2) and (($year mod 4) = 0)">29</xsl:when>
			<xsl:when test="$mo = 2">28</xsl:when>
			<xsl:when test="$mo = 3">31</xsl:when>
			<xsl:when test="$mo = 4">30</xsl:when>
			<xsl:when test="$mo = 5">31</xsl:when>
			<xsl:when test="$mo = 6">30</xsl:when>
			<xsl:when test="$mo = 7">31</xsl:when>
			<xsl:when test="$mo = 8">31</xsl:when>
			<xsl:when test="$mo = 9">30</xsl:when>
			<xsl:when test="$mo = 10">31</xsl:when>
			<xsl:when test="$mo = 11">30</xsl:when>
			<xsl:when test="$mo = 12">31</xsl:when>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="UTCDate">
	<xsl:param name="DateTime" />
	<xsl:variable name="year">
		<xsl:value-of select="number(substring($DateTime,1,4))" />
	</xsl:variable>
	<xsl:variable name="month">
		<xsl:value-of select="number(substring($DateTime,5,2))" />
	</xsl:variable>
	<xsl:variable name="day">
		<xsl:value-of select="number(substring($DateTime,7,2))" />
	</xsl:variable>
	<xsl:variable name="hh">
		<xsl:value-of select="number(substring($DateTime,9,2))" />
	</xsl:variable>
	<xsl:variable name="mm">
		<xsl:value-of select="number(substring($DateTime,11,2))" />
	</xsl:variable>
	<xsl:variable name="ss">
		<xsl:value-of select="substring($DateTime,13,2)" />
	</xsl:variable>
	<xsl:variable name="sign">
		<xsl:value-of select="substring($DateTime,16,1)" />
	</xsl:variable>
	<xsl:variable name="tzh">
		<xsl:value-of select="number(substring($DateTime,17,2))" />
	</xsl:variable>
	<xsl:variable name="tzm">
		<xsl:value-of select="number(substring($DateTime,19,2))" />
	</xsl:variable>
	<xsl:variable name="stzh">
		<xsl:choose>
			<xsl:when test="$sign = '-'">
				<xsl:value-of select="-($tzh)"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$tzh"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<xsl:variable name="stzm">
		<xsl:choose>
			<xsl:when test="$sign = '-'">
				<xsl:value-of select="-($tzm)"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$tzm"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	 <!--Calculate last day of current month -->
	<xsl:variable name="maxday">
		<xsl:call-template name="DayMonth">
			<xsl:with-param name="mo" select="$month"/>
			<xsl:with-param name="year" select="$year"/>
		</xsl:call-template>
	</xsl:variable>

	 <!--Calculate previous day -->
	<xsl:variable name="dayminus">
		<xsl:choose>
			<!--Set to last day of previous month-->
			<xsl:when test="$day &lt;= 1">
				<xsl:call-template name="DayMonth">
					<xsl:with-param name="mo" select="($month)-1"/>
					<xsl:with-param name="year" select="$year"/>
				</xsl:call-template>
			</xsl:when>
			<!--Decrement day-->
			<xsl:otherwise>
				<xsl:value-of select="($day)-1"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	
	 <!--Calculate next day -->
	<xsl:variable name="dayplus">
		<xsl:choose>
			<!--If last day of current month-->
			<xsl:when test="$day = $maxday">
				<xsl:value-of select="1"/>
			</xsl:when>
			<!--Increment day-->
			<xsl:otherwise>
				<xsl:value-of select="($day)+1"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<xsl:variable name="dayadj">
		<xsl:choose>
			<!--TimeZone was positive-->
			<xsl:when test="$hh &lt; $stzh">
				<xsl:value-of select="$dayminus"/>
				<!--Remove one day-->
			</xsl:when>
			<xsl:when test="($hh &lt;= $stzh) and ($mm &lt; $stzm)">
				<xsl:value-of select="$dayminus"/>
				<!--Remove one day-->
			</xsl:when>
			<!--TimeZone was negative-->
			<xsl:when test="((($hh)-($stzh)) &gt;= 23) and ((($mm)-($stzm)) &gt;= 60)">
				<xsl:value-of select="$dayplus"/>
				<!--Add one day-->
			</xsl:when>
			<xsl:when test="(($hh)-($stzh)) &gt;= 24">
				<xsl:value-of select="$dayplus"/>
				<!--Add one day-->
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$day"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<xsl:variable name="monthadj">
		<xsl:choose>
			<!--Handle +XX timezone-->
			<xsl:when test="($hh &lt; $stzh) and ($day = 1) and ($month = 1)">
				<xsl:value-of select="12"/>
			</xsl:when>
			<xsl:when test="($hh &lt;= $stzh) and ($mm &lt; $stzm) and ($day =
1) and ($month = 1)">
				<xsl:value-of select="12"/>
			</xsl:when>
			<xsl:when test="($hh &lt; $stzh) and ($day = 1) and ($month &gt; 1)">
				<xsl:value-of select="($month)-1"/>
			</xsl:when>
			<xsl:when test="($hh &lt;= $stzh) and ($mm &lt; $stzm) and ($day =
1) and ($month &gt; 1)">
				<xsl:value-of select="($month)-1"/>
			</xsl:when>
			<!--Handle -XX timezone-->
			<xsl:when test="((($hh)-($stzh)) &gt;= 24) and ($day = $maxday) and
($month = 12)">
				<xsl:value-of select="1"/>
			</xsl:when>
			<xsl:when test="((($hh)-($stzh)) &gt;= 24) and ($day = $maxday) and
($month &lt; 12)">
				<xsl:value-of select="($month)+1"/>
			</xsl:when>
			<xsl:when test="((($hh)-($stzh)) &gt;= 23) and ((($mm)-($stzm))
&gt;= 60) and ($day = $maxday) and ($month = 12)">
				<xsl:value-of select="1"/>
			</xsl:when>
			<xsl:when test="((($hh)-($stzh)) &gt;= 23) and ((($mm)-($stzm))
&gt;= 60) and ($day = $maxday) and ($month &lt; 12)">
				<xsl:value-of select="($month)+1"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$month"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<xsl:variable name="yearadj">
		<xsl:choose>
			<!--Handle +XX timezone-->
			<xsl:when test="($hh &lt; $stzh) and ($day = 1) and ($month = 1)">
				<xsl:value-of select="($year)-1"/>
			</xsl:when>
			<xsl:when test="($hh &lt;= $stzh) and ($mm &lt; $stzm) and ($day =
1) and ($month = 1)">
				<xsl:value-of select="($year)-1"/>
			</xsl:when>
			<!--Handle -XX timezone-->
			<xsl:when test="((($hh)-($stzh)) &gt;= 24) and ($day = $maxday) and
($month = 12)">
				<xsl:value-of select="($year)+1"/>
			</xsl:when>
			<xsl:when test="((($hh)-($stzh)) &gt;= 23) and ((($mm)-($stzm))
&gt;= 60) and ($day = $maxday) and ($month = 12)">
				<xsl:value-of select="($year)+1"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$year"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<!--Calculate time in UTC -->
	<xsl:variable name="mmutc">
		<xsl:choose>
			<xsl:when test="$mm &lt; $stzm">
				<xsl:value-of select="(60+$mm)-($stzm)"/>
			</xsl:when>
			<xsl:when test="(($mm)-($stzm)) &gt;= 60">
				<xsl:value-of select="(($mm)-($stzm))-60"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="($mm)-($stzm)"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<xsl:variable name="hhutc">
		<xsl:choose>
			<!--Handle +XX timezone-->
			<xsl:when test="($hh &lt;= $stzh) and ($mm &lt; $stzm)">
				<xsl:value-of select="(23+$hh)-($stzh)"/>
			</xsl:when>
			<xsl:when test="($hh &lt; $stzh) and ($mm &gt;= $stzm)">
				<xsl:value-of select="(24+$hh)-($stzh)"/>
			</xsl:when>
			<xsl:when test="($hh &gt; $stzh) and ($mm &lt; $stzm)">
				<xsl:value-of select="($hh)-($stzh)-1"/>
			</xsl:when>
			<!--Handle -XX timezone-->
			<xsl:when test="((($hh)-($stzh)) &gt;= 23) and ((($mm)-($stzm)) &gt;= 60)">
				<xsl:value-of select="(($hh)-($stzh)+1) mod 24"/>
			</xsl:when>
			<xsl:when test="((($hh)-($stzh)) &gt; 23) and ((($mm)-($stzm)) &lt; 60)">
				<xsl:value-of select="(($hh)-($stzh)) mod 24"/>
			</xsl:when>
			<xsl:when test="((($hh)-($stzh)) &lt; 23) and ((($mm)-($stzm)) &gt;= 60)">
				<xsl:value-of select="(($hh)-($stzh))+1"/>
			</xsl:when>
			<!--We haven't changed day, month, year-->
			<xsl:otherwise>
				<xsl:value-of select="($hh)-($stzh)"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<xsl:value-of select="$yearadj"/>
	<xsl:if test="($monthadj) &lt; 10"><xsl:value-of select="'0'"/></xsl:if>
	<xsl:value-of select="$monthadj"/>
	<xsl:if test="($dayadj) &lt; 10"><xsl:value-of select="'0'"/></xsl:if>
	<xsl:value-of select="$dayadj"/>
	<xsl:if test="($hhutc) &lt; 10"><xsl:value-of select="'0'"/></xsl:if>
	<xsl:value-of select="$hhutc"/>
	<xsl:if test="($mmutc) &lt; 10"><xsl:value-of select="'0'"/></xsl:if>
	<xsl:value-of select="$mmutc"/>
	<xsl:value-of select="$ss"/>
	<xsl:value-of select="' +0000'"/>
	</xsl:template>


Current Thread
Keywords