0

This question is unique in that fact that I had a look at the two answers that came up as being similar - and those did not solve my problem. I want the timeShift field to be added to the html as a text value and not as a property of the tag.

I have the following xml, and would like to do some time manipulation on the timeShift field, in order for it to be in the format: HH:MM:SS.

How can I do this in xsl?

The following is my current xsl file:

    <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:strip-space elements="*"/>

<xsl:key name="party" match="newParty" use="@userId" />

<xsl:template match="/chatTranscript">
    <html>
        <head><link rel="stylesheet" type="text/css" href="/webrecall/css/chat.css"/></head>
        <header>Chat - <xsl:value-of select="@sessionId" /> - <xsl:value-of select="@startAt" /></header>
        <xsl:apply-templates/>
    </html>
</xsl:template>

<xsl:template match="newParty[userInfo/@userType='CLIENT']">
    <div class="ClientJoined" id="{@userId}">
        <label>Client: <xsl:value-of select="userInfo/@userNick" /></label>
        <label class="timeShiftLabel"><xsl:value-of select="@timeShift" /></label>
      </div>
</xsl:template>

<xsl:template match="newParty[userInfo/@userType='AGENT']">
    <div class="AgentJoined" id="{@userId}">
        <label>Agent: <xsl:value-of select="userInfo/@userNick" /></label>
        <label class="timeShiftLabel"><xsl:value-of select="@timeShift" /></label>
    </div>
</xsl:template> 

<xsl:template match="message">
    <xsl:variable name="party-class">
        <xsl:call-template name="lookup-class"/>
    </xsl:variable>
    <div class="Messages {$party-class}" id="{@eventId}">
        <label><xsl:value-of select="msgText" /></label>
        <label class="timeShiftLabel"><xsl:value-of select="@timeShift" /></label>
    </div>
</xsl:template>   
<xsl:template match="notice">
    <xsl:variable name="party-class">
        <xsl:call-template name="lookup-class"/>
    </xsl:variable>
    <div class="Notices {$party-class}" id="{@eventId}">
        <label><xsl:value-of select="noticeText" /></label>
        <label class="timeShiftLabel"><xsl:value-of select="@timeShift" /></label>
    </div>
</xsl:template>

<xsl:template match="partyLeft">
    <xsl:variable name="party-class">
        <xsl:call-template name="lookup-class"/>
    </xsl:variable>
    <div class="Notices {$party-class}" id="{@eventId}">
        <label><xsl:value-of select="reason" /></label>
        <label class="timeShiftLabel"><xsl:value-of select="@timeShift" /></label>
    </div>
</xsl:template>

<xsl:template name="lookup-class">
    <xsl:variable name="party-type" select="key('party', @userId)/userInfo/@userType" />
    <xsl:choose>
        <xsl:when test="$party-type='CLIENT'">Client</xsl:when>
        <xsl:when test="$party-type='AGENT'">Agent</xsl:when>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

The following is the xml:

    <?xml version="1.0"?><chatTranscript startAt="2015-06-04T09:07:40Z" sessionId="0003CaANX11G00HD">
    <newParty userId="00955570155B0000" eventId="1" timeShift="0" visibility="ALL">
        <userInfo personId="" userNick="PhilC" userType="CLIENT" protocolType="FLEX" timeZoneOffset="120"/>
        <userData>
            <item key="EmailAddress"/>
            <item key="FirstName">Phil</item>
            <item key="IdentifyCreateContact">3</item>
            <item key="LastName">Collins</item>
            <item key="MediaType">chat</item>
        </userData>
    </newParty>
    <newParty userId="0095557015600002" eventId="2" timeShift="4" visibility="ALL">
        <userInfo personId="" userNick="system" userType="EXTERNAL" protocolType="ESP" timeZoneOffset="0"/>
    </newParty>
    <message userId="0095557015600002" eventId="3" timeShift="4" visibility="ALL">
        <msgText>agent will be with you shortly</msgText>
    </message>
    <newParty userId="00955570156E0003" eventId="4" timeShift="19" visibility="ALL">
        <userInfo personId="emailqa" userNick="emailqa" userType="AGENT" protocolType="BASIC" timeZoneOffset="120"/>
    </newParty>
    <message userId="00955570155B0000" eventId="6" timeShift="22" visibility="ALL">
        <msgText msgType="text" treatAs="NORMAL">hellO?</msgText>
    </message>
    <message userId="00955570156E0003" eventId="9" timeShift="26" visibility="ALL">
        <msgText treatAs="NORMAL">hi Phil</msgText>
    </message>
    <message userId="00955570156E0003" eventId="11" timeShift="28" visibility="ALL">
        <msgText treatAs="NORMAL">whatsup?</msgText>
    </message>
    <message userId="00955570155B0000" eventId="14" timeShift="45" visibility="ALL">
        <msgText msgType="text" treatAs="NORMAL">we're sitting next to each other but we're sending IMs  </msgText>
    </message>
    <message userId="00955570156E0003" eventId="17" timeShift="54" visibility="ALL">
        <msgText treatAs="NORMAL">hehehe</msgText>
    </message>
    <message userId="00955570156E0003" eventId="19" timeShift="56" visibility="ALL">
        <msgText treatAs="NORMAL">indeed</msgText>
    </message>
    <partyLeft userId="00955570156E0003" askerId="00955570156E0003" eventId="21" timeShift="77" visibility="ALL">
        <reason code="1">left with request to close if no agents</reason>
    </partyLeft>
    <partyLeft userId="00955570155B0000" askerId="00955570156E0003" eventId="22" timeShift="77" visibility="ALL">
        <reason code="4">removed by other party</reason>
    </partyLeft>
</chatTranscript>

So the question is how can I take the timeShift integer value as input(its indicative of the time lapsed in seconds), and manipulate it to be a duration, in the format HH:mm:ss.

Harriet
  • 1,633
  • 5
  • 22
  • 36

1 Answers1

0

Get acquainted with description of the following functions:

  • substring - get a part of a string,
  • xs:time(timestring) - casting of a string into xs:time type,
  • format-time - get a formatted string from a xs:time variable.

The above functions may be useful especially if you intend to perform some calculations on time values.

Another solution is just to extract required substrings from source string (e.g. hour, minute and second part) using substring function. Then you can create the output string, using concat function.

Edit as of 13.02.2017

I created an example given below.

<?xml version="1.0" encoding="UTF-8"?>
<Main>
  <Record timeShift="17" cause="A1">Abcd efgh ijlk</Record>
  <Record timeShift="85" cause="A2">Mnop qrst uvw xyz</Record>
</Main>

Below you have an example XSL converting timeShift attribute to mm:ss format.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>

  <xsl:template match="@timeShift">
    <xsl:attribute name="timeShift">
      <xsl:call-template name="format-duration"/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template name="format-duration">
    <xsl:param name="value" select="." />
    <xsl:param name="alwaysIncludeHours" select="false()" />
    <xsl:param name="includeSeconds" select="true()" />

    <xsl:if test="$value > 3600 or $alwaysIncludeHours">
      <xsl:value-of select="concat(format-number($value div 3600, '00'), ':')"/>
    </xsl:if>
    <xsl:value-of select="format-number($value div 60 mod 60, '00')" />
    <xsl:if test="$includeSeconds">
      <xsl:value-of select="concat(':', format-number($value mod 60, '00'))" />
    </xsl:if>
  </xsl:template>  

  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
  </xsl:template>
</xsl:stylesheet>

format-duration template is copied from Seconds to Time in XSLT mentioned in a comment to this post.

And back to your XSL source: Change each case of

<label class="timeShiftLabel"><xsl:value-of select="@timeShift" /></label>

to:

<label class="timeShiftLabel">
  <xsl:call-template name="format-duration">
    <xsl:with-param name="value" select="@timeShift"/>
    <xsl:with-param name="alwaysIncludeHours" select="true()" />
  </xsl:call-template>
</label>

Of course, since you call format-duration template, you should include it in your XSL as well.

Community
  • 1
  • 1
Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41
  • Neither of these functions will help to convert a text string of `"17"` to a HH:MM:SS representation of time (whatever that might be). And just pointing to some functions is not an answer anyway. – michael.hor257k Feb 10 '17 at 18:07
  • I assumed that _timeShift_ may include more "components", e.g. first 2 digits are hours, next 2 (if any) - minutes and another 2 (if any) - seconds. In such case you have to extract particular fragments of _timeShift_. So: _substring_ is needed to extract particular components, casting is needed to obtain _time_ type value and _format-time_ - for printing purposes. – Valdi_Bo Feb 10 '17 at 20:33
  • say timeShift is 72, that would be in seconds, and I would like to then display it as 1:12 - that would indicate one minute, 12 seconds. I am not too sure if an actual chat will be more than one hour, but I plan to cater for that anyway. – Harriet Feb 11 '17 at 19:25
  • See http://stackoverflow.com/questions/15370152/seconds-to-time-in-xslt this should solve your issue. – Valdi_Bo Feb 11 '17 at 20:06
  • Hi @Valdi_Bo - I had a look at the example you sent, but unfortunately I am not that well versed in xsl. I've updated my original post to contain all my code, and hopefully someone here can help me figure it out. – Harriet Feb 13 '17 at 08:50
  • Copy/paste programming has its pitfalls. The template you have copied produces incorrect results. – michael.hor257k Feb 13 '17 at 11:12
  • In my edit (earlier today) I forgot about the requirement to include hours. So I added the missing parameter (_alwaysIncludeHours_).. – Valdi_Bo Feb 13 '17 at 14:51