xsl-list
[Top] [All Lists]

Re: [xsl] different evaluations on sibling elements ...

2013-08-27 04:53:18
Ignoring all your existing logic, I think the summary can be done something 
like this:

<xsl:for-each-group select="//entry" group-by="statistics_category">
  <xsl:value-of select="current-grouping-key(), ': ', 
format-number(sum(current-group()/f:duration-in-hours(.), '0.00'))"/>
</xsl:for-each-group>

<xsl:function name="f:duration-in-hours" as="xs:double" >
  <xsl:param name="entry" as="element(entry)"/>
  <!-- TODO: add logic for the case where there's no following-siblng -->
  <xsl:variable name="this" select="dateTime(/isodate, time)"/>
  <xsl:variable name="next" select="dateTime(following-sibling::entry/isodate, 
following-sibling::entry/time)"/>
  <xsl:sequence select="($next - $this) div xs:duration('PT1H')"/>
</xsl:function>

Michael Kay
Saxonica

On 26 Aug 2013, at 17:33, Raimund Kammering wrote:

Hi,

i need to build up two tables listing periods between timestamps plus some 
categories. I got the math with evaluating the time periods running but am 
stuck on building additionally a summary table for the appearances of the 
categories. Here is what I have:

XML:
-------
<list>
 <url_base>/2013/06/09.02_n</url_base>
 <entry>
   <severity>STATISTICS</severity>
   <isodate>2013-02-09</isodate>
   <time>23:00:00</time>
   <statistics_category>Delivery</statistics_category>
 </entry>
 <entry>
   <severity>STATISTICS</severity>
   <isodate>2013-02-10</isodate>
   <time>00:37:33</time>
   <statistics_category>Tuning</statistics_category>
   <tuning>Problems</tuning>
 </entry>
 <entry>
   <severity>STATISTICS</severity>
   <isodate>2013-02-10</isodate>
   <time>02:59:03</time>
   <statistics_category>Delivery</statistics_category>
 </entry>
 <entry>
   <severity>STATISTICS</severity>
   <isodate>2013-02-10</isodate>
   <time>03:27:39</time>
   <statistics_category>Tuning</statistics_category>
   <tuning>Quality</tuning>
 </entry>
 <entry>
   <severity>STATISTICS</severity>
   <isodate>2013-02-10</isodate>
   <time>03:42:09</time>
   <statistics_category>Delivery</statistics_category>
 </entry>
 <entry>
   <severity>STATISTICS</severity>
   <isodate>2013-02-10</isodate>
   <time>04:18:11</time>
   <statistics_category>Down</statistics_category>
   <down>RF</down>
 </entry>
</list>

XSL:
-------
 <xsl:param name="url_base">
   <xsl:value-of select="/list/url_base"/>
 </xsl:param>

 <xsl:template name="statistics_details">

     <table>
     <tr><td colspan="3">Detailed statistics</td></tr>
     <tr><td></td><td></td><td>Start</td><td>End</td><td>duration 
[hours]</td><td>Category</td><td>Reason</td></tr>

   <xsl:for-each select="entry[severity!='DELETE']/statistics_category">
     <xsl:sort order="descending" select="../isodate"/>
     <xsl:sort order="descending" select="../time"/>

     <xsl:variable name="end_time">
       <xsl:choose>
         <xsl:when 
test="ancestor::entry/following-sibling::entry[severity!='DELETE']/statistics_category">
           <!-- FIXME - will fail if two or more consecutive deletes follow! 
-->
             <xsl:value-of 
select="ancestor::entry/following-sibling::entry[severity!='DELETE']/statistics_category/../time"/>
         </xsl:when>
         <!-- last log -->
         <xsl:otherwise>
           <xsl:choose>
             <xsl:when test="substring($url_base, string-length($url_base) 
)='M'">
               <xsl:value-of select="'15:00:00'"/>
             </xsl:when>
             <xsl:when test="substring($url_base, string-length($url_base) 
)='a'">
               <xsl:value-of select="'23:00:00'"/>
             </xsl:when>
             <xsl:when test="substring($url_base, string-length($url_base) 
)='n'">
               <xsl:value-of select="'07:00:00'"/>
             </xsl:when>
             <xsl:otherwise>
               <xsl:text>ERROR: Could not determine shift end</xsl:text>
             </xsl:otherwise>
           </xsl:choose>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:variable>

     <xsl:variable name="end_date">
       <xsl:choose>
         <xsl:when 
test="ancestor::entry/following-sibling::entry[severity!='DELETE']/statistics_category">
           <!-- FIXME - will fail if two or more consecutive deletes follow! 
-->
             <xsl:value-of 
select="ancestor::entry/following-sibling::entry[severity!='DELETE']/statistics_category/../isodate"/>
         </xsl:when>
         <xsl:otherwise>
           <xsl:choose>
             <xsl:when test="substring($url_base, string-length($url_base) 
)='M'">
               <xsl:value-of select="substring-before(date:date(),'+')"/>
             </xsl:when>
             <xsl:when test="substring($url_base, string-length($url_base) 
)='a'">
               <xsl:value-of select="substring-before(date:date(),'+')"/>
             </xsl:when>
             <xsl:when test="substring($url_base, string-length($url_base) 
)='n'">
               <xsl:choose>
                 <xsl:when test="substring(../time, 1, 1)!='0'">
                   <xsl:call-template name="date:add">
                     <xsl:with-param name="date-time" select="../isodate" />
                     <xsl:with-param name="duration" select="'P1D'" />
                   </xsl:call-template>
                 </xsl:when>
                 <xsl:otherwise>
                   <xsl:value-of select="../isodate"/>
                 </xsl:otherwise>
               </xsl:choose>
             </xsl:when>
             <xsl:otherwise>
               <xsl:value-of select="substring-before(date:date(),'+')"/>
             </xsl:otherwise>
           </xsl:choose>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:variable>

     <xsl:variable name="start_time" select="../time"/>

     <xsl:variable name="end" select="concat($end_date, 'T', $end_time)"/>
     <xsl:variable name="start" select="concat(../isodate, 'T', 
$start_time)"/>

     <xsl:variable name="time-diff-dur">
       <xsl:call-template name="date:difference">
         <xsl:with-param name="start" select="$start" />
         <xsl:with-param name="end" select="$end" />
       </xsl:call-template>
     </xsl:variable>

     <!-- The above returns a duration formatted string, so convert that to 
seconds: -->
     <xsl:variable name="time-diff-sec">
       <xsl:call-template name="duration2seconds">
         <xsl:with-param name="duration" select="$time-diff-dur" />
       </xsl:call-template>
     </xsl:variable>

     <tr>
       <td></td><td></td>
       <td><xsl:value-of select="$start_time"/></a></td>
       <td><xsl:value-of select="$end_time"/></td>
       <td><xsl:value-of select="format-number($time-diff-sec div 3600, 
'0.00')"/></td>
       <td><xsl:value-of select="."/></td>
       <xsl:choose>
           <xsl:when test=".='Tuning'">
               <td><xsl:value-of select="../Tuning"/></td>
           </xsl:when>
           <xsl:when test=".='Down'">
               <td><xsl:value-of select="../Down"/></td>
           </xsl:when>
           <xsl:otherwise>
               <td></td></xsl:otherwise>
       </xsl:choose>        
     </tr>

   </xsl:for-each>

 </table>    
 </xsl:template>

HTML Output:
-------------------
Detailed statistics
Start End     duration [hours]        Category
04:18:11      07:00:00        2.70    Down    RF
03:42:09      04:18:11        0.60    Delivery        
03:27:39      03:42:09        0.24    Tuning  Quality
02:59:03      03:27:39        0.48    Delivery        
00:37:33      02:59:03        2.36    Tuning  Problems
23:00:00      00:37:33        1.63    Delivery        

I completely omit here the stuff needed for the time difference calculation 
etc., since this all  works just fine and is quite impressive - thanks to the 
xsl-list's previous help!! But now I would like to have above the 'Detailed 
statistics' section a 'Statistics Summary' showing the sums for the 
statistics categories. So that the final html would look like this:

Desired HTML Output:
------------------------------
Statistics Summary
Delivery: 2.71        Tuning: 2.60            Down: 2.70

Detailed statistics
Start End     duration [hours]        Category
04:18:11      07:00:00        2.70    Down    RF
03:42:09      04:18:11        0.60    Delivery        
03:27:39      03:42:09        0.24    Tuning  Quality
02:59:03      03:27:39        0.48    Delivery        
00:37:33      02:59:03        2.36    Tuning  Problems
23:00:00      00:37:33        1.63    Delivery

I thought of several of the 'standard trick' like recursion and/or calling 
template with modes, but never got a clear picture how to manage it (this 
nasty thing with the needed relation between the two consecutive 'entry' 
elements …). Any idea on how to approach this would be greatly welcome!! 

And yes some of the calling logic I left out, since this is not the tricky 
part and the above should hopefully sketch the problem sufficiently (and for 
simplicity I left out the case of an entry having severity='DELETE' ;-)!?

Cheers,
Raimund








--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--