Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Adding Time in XSL

Status
Not open for further replies.

benjatado

Programmer
May 15, 2005
52
0
0
US
I am trying to find a way to get the sum (hh:mm:ss) of all descendant <time> element's values (mm:ss) in the XML.

The values of the descendant<time> elements are in mm:ss format, and I would like to be able to add all descendant <time> elements and rely on the XSLT processor to provide the correct hh:mm:ss total sum of all.

Is there a function for this type of math?

Thanks! -

benjatado
 
XSLT 1 does not provide functions to do this. You have 3 options:

1. Use extension functions (such as exslt)
2. Write your own extension function.
3. Write a recursive XSL function that takes a node-set of <time> elements and adds them up:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <xsl:template match="/">
    <xsl:call-template name="addTimes">
      <xsl:with-param name="times" select="//time"/>
      <xsl:with-param name="total" select="0"/>
    </xsl:call-template>
  </xsl:template>
  <xsl:template name="addTimes">
    <xsl:param name="times"/>
    <xsl:param name="total"/>
    <xsl:choose>
      <xsl:when test="$times">
        <xsl:call-template name="addTimes">
          <xsl:with-param name="times" select="msxsl:node-set($times)[position() &gt; 1]"/>
          <xsl:with-param name="total">
            <xsl:variable name="mins">
              <xsl:value-of select="substring-before($times[1], ':')"/>
            </xsl:variable>
            <xsl:variable name="secs">
              <xsl:value-of select="substring-after($times[1], ':')"/>
            </xsl:variable>
            <xsl:value-of select="$total + $secs + ($mins * 60)"/>
          </xsl:with-param>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="hrs">
          <xsl:value-of select="floor($total div 3600)"/>
        </xsl:variable>
        <xsl:variable name="mins">
          <xsl:value-of select="floor(($total mod 3600) div 60)"/>
        </xsl:variable>
        <xsl:variable name="secs">
          <xsl:value-of select="($total mod 3600) mod 60"/>
        </xsl:variable>
        <xsl:value-of select="concat($hrs, ':', format-number($mins, '00'), ':', format-number($secs, '00'))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Jon

"I don't regret this, but I both rue and lament it.
 
Jonty -

Nice... I am using the exlt namespace! :)
So what are these functions?

This nice example you provided was using the MSNS - correct? So I guess I am in luck using the exlt ns!?

-b
 
The EXSLT date functions, specifically the add-duration function. Although you'll have to first convert your time the correct duration format, and then write a template to add all the times in the node-set, so it would probably be easier just to use the example I wrote. If you can't use the MSXSL namespace, just replace it with the equivalent EXSLT node-set function.

Jon

"I don't regret this, but I both rue and lament it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top