Altering the date format in XSLT - datetime

I have a XSLT sheet that returns and formats a date as below:
<result column="name" isNull="false">2017-08-08</result>
<result column="display" isNull="false">08-08-2017</result>
Ideally, I would like the information to be displayed as 'Tuesday 08 July'. Is this possible?
The current XSLT is below:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="ArrayOfdateItem">
<date>
<name>
<xsl:apply-templates select="node()" />
</name>
<display>
<xsl:value-of select="concat(substring(node(),9,2),'-',substring(node(),6,2),'-',substring(node(),1,4))" />
</display>
</date>
</xsl:template>
</xsl:stylesheet>
XML:
<soap:Body>
<GetBulkyWasteDatesFromDate
xmlns="http://">
<GetBulkyWasteDatesFromDateInput>
<UPRN>{customerDetails/uprn}</UPRN>
<threshold>16:00:00</threshold>
<startDate>{startDate}</startDate>
<includeToday>false</includeToday>
<noOfAvailableDates>3</noOfAvailableDates>
</GetBulkyWasteDatesFromDateInput>
</GetBulkyWasteDatesFromDate>
</soap:Body>

To do this purely in XSLT 1.0 is a bit verbose. Consider the following example:
XML
<dates>
<date>2017-07-23</date>
<date>2017-07-24</date>
<date>2017-07-25</date>
<date>2017-07-26</date>
<date>2017-07-27</date>
<date>2017-07-28</date>
<date>2017-07-29</date>
</dates>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="date">
<date>
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="."/>
</xsl:call-template>
</date>
</xsl:template>
<xsl:template name="format-date">
<xsl:param name="date"/>
<xsl:variable name="year" select="substring($date,1, 4)"/>
<xsl:variable name="month" select="substring($date, 6, 2)"/>
<xsl:variable name="day" select="substring($date, 9, 2)"/>
<xsl:variable name="a" select="floor((14 - $month) div 12)"/>
<xsl:variable name="y" select="$year + 4800 - $a"/>
<xsl:variable name="m" select="$month + 12*$a - 3"/>
<xsl:variable name="JDN" select="$day + floor((153*$m + 2) div 5) + 365*$y + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045" />
<xsl:variable name="day-of-week" select="($JDN + 1) mod 7" />
<xsl:choose>
<xsl:when test="$day-of-week=0">Sunday </xsl:when>
<xsl:when test="$day-of-week=1">Monday </xsl:when>
<xsl:when test="$day-of-week=2">Tuesday </xsl:when>
<xsl:when test="$day-of-week=3">Wednesday </xsl:when>
<xsl:when test="$day-of-week=4">Thursday </xsl:when>
<xsl:when test="$day-of-week=5">Friday </xsl:when>
<xsl:when test="$day-of-week=6">Saturday </xsl:when>
</xsl:choose>
<xsl:value-of select="format-number($day, '00')" />
<xsl:choose>
<xsl:when test="$month=1"> January</xsl:when>
<xsl:when test="$month=2"> February</xsl:when>
<xsl:when test="$month=3"> March</xsl:when>
<xsl:when test="$month=4"> April</xsl:when>
<xsl:when test="$month=5"> May</xsl:when>
<xsl:when test="$month=6"> June</xsl:when>
<xsl:when test="$month=7"> July</xsl:when>
<xsl:when test="$month=8"> August</xsl:when>
<xsl:when test="$month=9"> September</xsl:when>
<xsl:when test="$month=10"> October</xsl:when>
<xsl:when test="$month=11"> November</xsl:when>
<xsl:when test="$month=12"> December</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<dates>
<date>Sunday 23 July</date>
<date>Monday 24 July</date>
<date>Tuesday 25 July</date>
<date>Wednesday 26 July</date>
<date>Thursday 27 July</date>
<date>Friday 28 July</date>
<date>Saturday 29 July</date>
</dates>

Related

Combining XML Nodes into a single node with an XSLT

I'm trying to edit some XML with a transform but I'm struggling to achieve my desired results.
I have some XML:
<FX>
<Order ATTRIBUTE1="ACTIVE" ATTRIBUTE2="CCY" />
<Attribute NAME="N1" VALUE="V1" />
<Attribute NAME="N2" VALUE="V2" />
<Attribute NAME="N3" VALUE="V3" />
</FX>
And I want to transform it to look like:
<FX>
<Order ATTRIBUTE1="ACTIVE" ATTRIBUTE2="CCY" />
<Attribute NAME="N1, N2, N3" VALUE="V1,V2,V3" />
</FX>
Is this possible? Can anyone offer any suggestions on how to do this with a transform?
You can use the following, Asp.NET compatable, XSLT-1.0 stylesheet to perform an XSLT transformation from your source XML to your destination XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/FX">
<xsl:copy>
<xsl:copy-of select="Order" />
<Attribute>
<xsl:attribute name="NAME">
<xsl:for-each select="Attribute">
<xsl:value-of select="#NAME" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="VALUE">
<xsl:for-each select="Attribute">
<xsl:value-of select="#VALUE" />
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</Attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Its output is:
<FX>
<Order ATTRIBUTE1="ACTIVE" ATTRIBUTE2="CCY"/>
<Attribute NAME="N1, N2, N3" VALUE="V1,V2,V3"/>
</FX>
In general, if you want to transform some nodes but keep the rest you use the identity transformation template as the starting point and then add templates that change those nodes you want to change:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="FX/Attribute[1]">
<xsl:copy>
<xsl:apply-templates select="#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="FX/Attribute[position() > 1]"/>
<xsl:template match="FX/Attribute[1]/#*">
<xsl:attribute name="{name()}">
<xsl:for-each select=". | ../following-sibling::Attribute/#*[name() = name(current())]">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyH9rNk

How to keep a pointer to the original data in a tumbling window

Following my inital question with simplified data, I try to adapt the given solution to my actual data.
I face now this problem:
what is the best way to group the <time> nodes (as anwsered) and keep a pointer to the source document. Preciselly, I need to access the parent node <trkpt> to copy the attributes in the output.
Input
<?xml version="1.0" encoding="UTF-8"?>
<gpx
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
creator="me"
version="1.1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 gpx.xsd">
<metadata>
<link href="http://www.garmin.com">
<text>Garmin International</text>
</link>
<time>2017-08-03T11:26:14Z</time>
</metadata>
<trk>
<name>Journal actif: 01 AOUT 2017 16:03</name>
<trkseg>
<trkpt lat="50.064145" lon="5.194660">
<ele>305.84</ele>
<time>2017-08-01T15:25:58Z</time>
</trkpt>
<trkpt lat="50.062084" lon="5.198431">
<ele>314.49</ele>
<time>2017-08-01T15:26:11Z</time>
</trkpt>
<trkpt lat="50.059504" lon="5.202687">
<ele>321.70</ele>
<time>2017-08-01T15:26:27Z</time>
</trkpt>
</trkseg>
</trk>
<trk>
<name>Journal actif: 01 AOUT 2017 17:26</name>
<trkseg>
<trkpt lat="50.058567" lon="5.203909">
<ele>323.62</ele>
<time>2017-08-01T15:26:32Z</time>
</trkpt>
<trkpt lat="50.055699" lon="5.207007">
<ele>330.35</ele>
<time>2017-08-01T15:26:46Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
Expected Output (partial view)
<trkseg>
<trkpt lat="50.064145" lon="5.194660">
<time>2017-08-03T11:26:14Z</time>
</trkpt>
My current xslt is as follow
It breaks at the line <xsl:attribute name="lat" select="../#lat"/>.
<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml file:///C:/Data/Google%20Drive/Projects%20-%20Coding/Xslt/Garmin/01.xml?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/mf" exclude-result-prefixes="xs mf" version="2.0" xpath-default-namespace="http://www.topografix.com/GPX/1/1">
<xsl:param name="stop" as="xs:dayTimeDuration" select="xs:dayTimeDuration('PT5M')"/>
<xsl:output indent="yes" method="xml" />
<xsl:function name="mf:group" as="element(trk)*">
<xsl:param name="dateTimes" as="xs:dateTime*"/>
<xsl:param name="stop" as="xs:dayTimeDuration"/>
<xsl:sequence select="mf:group($dateTimes[1], $dateTimes[position() gt 1], $stop)"/>
</xsl:function>
<xsl:function name="mf:group" as="element(trk)*">
<xsl:param name="group" as="xs:dateTime*"/>
<xsl:param name="dateTimes" as="xs:dateTime*"/>
<xsl:param name="stop" as="xs:dayTimeDuration"/>
<xsl:variable name="next" as="xs:dateTime?" select="$dateTimes[1]"/>
<xsl:variable name="end" as="xs:dateTime" select="$group[last()]"/>
<xsl:choose>
<xsl:when test="not(exists($next))">
<xsl:sequence select="mf:wrap($group)"/>
</xsl:when>
<xsl:when test="$next - $end gt $stop">
<xsl:sequence select="mf:wrap($group)"/>
<xsl:sequence select="mf:group($next, $dateTimes[position() gt 1], $stop)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(($group, $next), $dateTimes[position() gt 1], $stop)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="mf:wrap" as="element(trk)">
<xsl:param name="dateTimes" as="xs:dateTime*"/>
<trk xmlns="http://www.topografix.com/GPX/1/1">
<name>TBC</name>
<trkseg>
<xsl:for-each select="$dateTimes">
<trkpt>
<xsl:attribute name="lat" select="../#lat"/>
<xsl:attribute name="lon" select="../#lon"/>
<time>
<xsl:value-of select="."/>
</time>
</trkpt>
</xsl:for-each>
</trkseg>
</trk>
</xsl:function>
<xsl:template match="gpx">
<gpx
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
creator="me"
version="1.1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 gpx.xsd">
<xsl:sequence select="mf:group(.//trkpt/time/xs:dateTime(.), $stop)"/>
</gpx>
</xsl:template>
</xsl:stylesheet>
In that case you would need to rewrite the functions to pass on and handle the elements (like the trkpt elements) and then inside the functions you would need to compute the xs:dateTime for the comparison), here is an attempt to fix the functions, I haven't tested that thouroughly though:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/mf" exclude-result-prefixes="xs mf" version="2.0" xpath-default-namespace="http://www.topografix.com/GPX/1/1">
<xsl:param name="stop" as="xs:dayTimeDuration" select="xs:dayTimeDuration('PT5M')"/>
<xsl:output indent="yes" method="xml" />
<xsl:strip-space elements="*"/>
<xsl:function name="mf:group" as="element(trk)*">
<xsl:param name="trktpts" as="element(trkpt)*"/>
<xsl:param name="stop" as="xs:dayTimeDuration"/>
<xsl:sequence select="mf:group($trktpts[1], $trktpts[position() gt 1], $stop)"/>
</xsl:function>
<xsl:function name="mf:group" as="element(trk)*">
<xsl:param name="group" as="element(trkpt)*"/>
<xsl:param name="trkpts" as="element(trkpt)*"/>
<xsl:param name="stop" as="xs:dayTimeDuration"/>
<xsl:variable name="next" as="element(trkpt)?" select="$trkpts[1]"/>
<xsl:variable name="nextDateTime" as="xs:dateTime?" select="$next/time/xs:dateTime(.)"/>
<xsl:variable name="end" as="xs:dateTime" select="$group[last()]/time/xs:dateTime(.)"/>
<xsl:choose>
<xsl:when test="not(exists($next))">
<xsl:sequence select="mf:wrap($group)"/>
</xsl:when>
<xsl:when test="$nextDateTime - $end gt $stop">
<xsl:sequence select="mf:wrap($group)"/>
<xsl:sequence select="mf:group($next, $trkpts[position() gt 1], $stop)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(($group, $next), $trkpts[position() gt 1], $stop)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="mf:wrap" as="element(trk)">
<xsl:param name="trkpts" as="element(trkpt)*"/>
<trk>
<name>TBC</name>
<trkseg>
<xsl:apply-templates select="$trkpts"/>
</trkseg>
</trk>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="trkpt/ele"/>
<xsl:template match="gpx">
<gpx
creator="me"
version="1.1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 gpx.xsd">
<xsl:sequence select="mf:group(.//trkpt, $stop)"/>
</gpx>
</xsl:template>
</xsl:stylesheet>

Recursive loop in Xslt 1.0

I am working on a recursive loop. Below is the sample code.
The loop gets executed only once. It is not executing until it reaches the maximum count (20 times).
Can you please help if this is an issue?
Thanks,
Raj
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:xdoxslt='http://www.oracle.com/XSL/Transform/java/oracle.apps.xdo.template.rtf.XSLTFunctions'>
<xsl:output method="text" omit-xml-declaration="yes" />
<xsl:variable name="nl">
<xsl:value-of select="'
'"/>
<xsl:text xml:space="preserve">
</xsl:text>
</xsl:variable>
<xsl:template match = "ARCHIVE_CHEQUE_WRITER">
<xsl:for-each select="CHEQUE">
<xsl:variable name="ded" select="./AC_DEDUCTIONS"/>
<xsl:variable name="dedcount" select="count($ded)"/>
<xsl:variable name="earn" select="./AC_EARNINGS"/>
<xsl:variable name="earncount" select="count($earn)"/>
<xsl:value-of select="$dedcount"/>
<xsl:value-of select="$nl"/>
<xsl:value-of select="$earncount"/>
<xsl:value-of select="$nl"/>
<xsl:text>Starting New Record*******</xsl:text>
<xsl:value-of select="$nl"/>
<xsl:for-each select="./AC_DEDUCTIONS">
<xsl:text>This is sample template</xsl:text>
<xsl:value-of select="$nl"/>
</xsl:for-each>
<xsl:value-of select="$nl"/>
<xsl:value-of select="$nl"/>
<xsl:call-template name="recursive-loop">
<xsl:with-param name="pCount" select="20"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="recursive-loop">
<xsl:param name="pStart" select="1"/>
<xsl:param name="pCount"/>
<xsl:text> value of parameters</xsl:text>
<xsl:value-of select="$nl"/>
<xsl:value-of select="$pStart"/>
<xsl:value-of select="$pCount"/>
<xsl:value-of select="$nl"/>
<xsl:if test="$pCount > pStart">
<xsl:call-template name="recursive-loop">
<xsl:with-param name="pStart" select="$pStart+1"/>
<xsl:with-param name="pCount" select="$pCount"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
You forgot to use $ for variable pStart in the template
<xsl:if test="$pCount > $pStart">
<xsl:call-template name="recursive-loop">
<xsl:with-param name="pStart" select="$pStart+1"/>
<xsl:with-param name="pCount" select="$pCount"/>
</xsl:call-template>
</xsl:if>

Display Images from media directory using media picker not working

I am using Umbraco v6.1.6 and what I want is simply display the images from the media directory I select using media picker.
The content of media directory is as below:
And I have created an XSLT file named ImageSlider.xslt and the content of that file are as below:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umb="urn:umbraco.library"
exclude-result-prefixes="umb"
>
<xsl:output method="html" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<xsl:template match="/">
<xsl:variable name="media" select="umb:GetMedia(1088, 0)" />
<xsl:if test="$media">
<img src="{$media/umbracoFile}" alt="{$media/altText}" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
here 1088 is the ID of the banner directory but it is not working at all. I am new to this.
Can anyone please help me ?
I'm assuming you want to select the folder and list all images underneath it. At the moment, your code is just trying to display the folder. You need something like this...
In my example, I'm using a multi-node tree picker and you can select images and folders, rendering out a csv. It will loop through it all and list out all the images
<xsl:for-each select="$source/value">
<xsl:variable name="imageId" select="number(current())" />
<xsl:if test="$imageId > 0">
<xsl:variable name="media" select="umbraco.library:GetMedia($imageId, 0)" />
<xsl:choose>
<xsl:when test="local-name($media) = 'Image'">
<xsl:call-template name="ImageBox">
<xsl:with-param name="imageId" select="$imageId"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="local-name($media) = 'Folder'">
<xsl:call-template name="LoopFolders">
<xsl:with-param name="folderId" select="$imageId"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="LoopFolders">
<xsl:param name="folderId"/>
<xsl:variable name="media" select="umbraco.library:GetMedia($folderId, 0)" />
<xsl:variable name="alt" select="$media/#nodeName" />
<div id="gallery">
<xsl:for-each select="umbraco.library:GetMedia($folderId, true())/Image">
<xsl:call-template name="ImageBox">
<xsl:with-param name="imageId" select="number(#id)"/>
</xsl:call-template>
</xsl:for-each>
</div>
</xsl:template>
<xsl:template name="ImageBox">
<xsl:param name="imageId"/>
<xsl:if test="$imageId > 0">
<xsl:variable name="media" select="umbraco.library:GetMedia($imageId, 0)" />
<xsl:if test="$media">
<xsl:variable name="url" select="$media/umbracoFile" />
<xsl:variable name="width" select="$media/umbracoWidth" />
<xsl:variable name="height" select="$media/umbracoHeight" />
<xsl:variable name="alt" select="$media/#nodeName" />
<img src="{$url}" alt="{$alt}" width="{$width}" height="{$height}" />
</xsl:if>
</xsl:if>
</xsl:template>

XSLT Informal Time Translation

I'm currently working on a translation of documents for importing as XML to another system, and this involves the translation of a quite informal representation of time, such as the following:
<estimated-time>15 mins<estimated-time>
And I need to translate this to something like the following:
<tr:estimated_time>00:15:00</tr:estimated_time>
I've messed around with tokenizing, substrings, and the various time functions and haven't been able to come up with anything, though I am quite inexperienced in XSLT.
Following Jirka's answer, I tried the following:
<xsl:template match="estimated-time">
<tr:estimated_time>
<xsl:value-of select="time:parseTime(./text(), 'hours')"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="time:parseTime(./text(), 'mins')"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="time:parseTime(./text(), 'seconds')"/>
</tr:estimated_time>
</xsl:template>
<xsl:function name="time:parseTime">
<xsl:param name="testedString"/>
<xsl:param name="lookingFor"/>
<xsl:variable name="tokens" select="tokenize($testedString, ' ')" />
<xsl:variable name="out">
<xsl:choose>
<xsl:when test="$tokens[. = $lookingFor]">
<xsl:variable name="pos" select="index-of($tokens, $lookingFor)-1"/>
<xsl:value-of select="$tokens[$pos]"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>00</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="if (string-length($out)=1) then concat('0', $out) else $out"/>
</xsl:function>
Which always resulted in:
<tr:estimated_time>00:00:00</tr:estimated_time>
Any assistance would be greatly appreciated.
Update: it works! There were some weird newlines all over the original that I hadn't spotted, which were preventing it from working.
Might be there is a more sofisticated or cleaner solution but using tokenizing it should be done for example in this way
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:tst="test">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<times>
<xsl:apply-templates select="times/time" />
</times>
</xsl:template>
<xsl:template match="time">
<time>
<xsl:value-of select="tst:getSomething(.,'hours')" />
<xsl:text>:</xsl:text>
<xsl:value-of select="tst:getSomething(.,'mins')" />
<xsl:text>:</xsl:text>
<xsl:value-of select="tst:getSomething(.,'sec')" />
</time>
</xsl:template>
<xsl:function name="tst:getSomething">
<xsl:param name="testedString" />
<xsl:param name="lookingFor" />
<xsl:variable name="tokens" select="tokenize($testedString, ' ')" />
<xsl:variable name="tmp">
<xsl:choose>
<xsl:when test="$tokens[. = $lookingFor]">
<xsl:variable name="pos" select="index-of($tokens, $lookingFor) - 1" />
<xsl:value-of select="$tokens[$pos]" />
</xsl:when>
<xsl:otherwise>
<xsl:text>00</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="if (string-length($tmp) = 1) then concat('0', $tmp) else $tmp" />
</xsl:function>
</xsl:stylesheet>
It produces output
<?xml version="1.0" encoding="UTF-8"?>
<times>
<time>05:30:00</time>
<time>00:05:00</time>
</times>

Resources