Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old September 23rd, 2005, 01:35 PM
Authorized User
 
Join Date: Jul 2005
Location: , , .
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default Xpath: sum function

Hi all,

Bare with me here so I can explain to you my problem.

I have to nodes are listed below:

What I needed to do here is I want to find the sum of the time from Node1 with the Time range given by Node 2

For example: The time frame from Node 2 is given as:
<Time From="2005-06-06T06:00:00" To="2005-06-06T07:54:37" TimeId="1">

So I want to find the sum of the time frame in Node 1 that is within the Time fram of From="2005-06-06T06:00:00" To="2005-06-06T07:54:37.
The difference between the StartTime and EndTime from Node one is calculated already and it is in the <Time>1122.0</Time> node. All I want is to compare the given ST and ET from Node 1 with the Time frame given in Node 2 and add the <Time>xxxx.x</Time> together as a sub-total time.

So in the XML Fragmentation below I will have two three different sub-total time.
Sub Total1: The first one would be sum(1122.0 +3600.0)
Sub Total2: The first one would be sum(168.0 +603.0)
Sub Total3: The first one would be 0.

I don't know enough xlst to get the sum from each separate time frame.
If this were to be in like C# then it would be like

C# Code fragment to show what I want to do in xslt
int iSubTotal = 0
datetime dtFrom
datetime dtTo
datetime dtST
datetime dtET
int iTime=0;

for each Node 2
  //get the Time frame from Node 2
   dtTo = To
   dtFrom = From

  for each Node 1
    //Get the ST and ET
    dtST = ST
    dtET = ET

    //compare
    if (dtST >= dtFrom and dtET <= dtTo)
      iSubTotal = iSubTotal + iTime
    end if
  end for
  print the iSubTotal
end for

If anyone can help me out with somehow get the Sub Total, that would be greatly appreciated!

Thanks,

Grace



**************************XMLFRAGMENTATION******** ******************
Node1:
<Node Name = "Test1'>
  <DT Name="AS">
   <Inc Desc="Stopped">
    <IRD>
     <ST>2005-06-06T06:00:00</ST>
     <ET>2005-06-06T06:18:42</ET>
     <Time>1122.0</Time>
    </IRD>

    <IRD>
     <ST>2005-06-06T06:19:42</ST>
     <ET>2005-06-06T07:19:42</ET>
     <Time>3600.0</Time>
    </IRD>

    <IRD>
     <ST>2005-06-06T07:57:33</ST>
     <ET>2005-06-06T08:00:21</ET>
     <Time>168.0</Time>
    </IRD>

    <IRD>
     <ST>2005-06-06T08:07:45</ST>
     <ET>2005-06-06T08:17:48</ET>
     <Time>603.0</Time>
    </IRD>

    <IRD>
     <ST>2005-06-06T08:27:44</ST>
     <ET>2005-06-06T09:38:53</ET>
     <Time>4269.0</Time>
    </IRD>
</Node>

Node 2: Node1 is based on the time frame in Node 2
<Node Name="Test2">
 <DT2 Name="AS"></DT2>
 <Identifier Name="Time Intervals" Value="Overall" Time="2005-06-06T00:00:00" ET="2005-06-07T00:00:00" Duration="86400">
  <Identifier Name="Production Shifts" Value="10 hr Shifts Days" Time="2005-06-06T06:00:00" ET="2005-06-06T16:00:00" Duration="36000">
   <Identifier Name="size" Value="16.0" Time="2005-06-02T14:16:11" ET="2005-06-06T09:50:56" Duration="329685">
    <Identifier Name="gauge" Value="375" Time="2005-06-03T12:29:59" ET="2005-06-06T07:54:37" Duration="242678">
     <Time From="2005-06-06T06:00:00" To="2005-06-06T07:54:37" TimeId="1">
      <DataType ID="206" Name="Test Variables [Lenght and Weight]">
       <Variable Name="Primary Weight" Type="N" Unit="Kgs">
        <VRD Value="2634.0000" Time="2005-06-06T06:57:50"></VRD>
    <VRD Value="2634.0000" Time="2005-06-06T06:58:02"></VRD>
       </Variable>
      </DataType>
     </Time>
    </Identifier>

    <Identifier Name="gauge" Value="500" Time="2005-06-06T07:54:37" ET="2005-06-06T09:50:56" Duration="7523">
     <Time From="2005-06-06T07:54:37" To="2005-06-06T09:50:56" TimeId="6">
      <DataType ID="206" Name="Triggered Variables [Lenght and weight]">
      <Variable Name="Prime Weight" Type="N" Unit="Lbs">
       <VRD Value="3322.0000" Time="2005-06-06T08:03:47"></VRD>
       <VRD Value="3322.0000" Time="2005-06-06T08:04:26"></VRD>
      </Variable>
    </Identifier>
   </Identifier>

    <Identifier Name="Tube size" Value="10 x 6" Time="2005-06-06T09:50:56" ET="2005-06-06T14:36:55" Duration="17159"
     <Identifier Name="Tube gauge" Value="500" Time="2005-06-06T09:50:56" ET="2005-06-06T10:00:00" Duration="7523">
      <Time From="2005-06-06T09:50:56" To="2005-06-06T10:00:00" TimeId="8">
       <DataType ID="206" Name="Triggered Variables [Lenght and weight]">
        <Variable Name="Prime Weight" Type="N" Unit="Lbs">
         <VRD Value="1226.0000" Time="2005-06-06T09:51:07"></VRD>
         <VRD Value="1226.0000" Time="2005-06-06T09:51:16"></VRD>
        </Variable>
       </DataType>
      </Time>
     </Identifier>
    </Identifier>
  </Identifier>
</Node>
Reply With Quote
  #2 (permalink)  
Old September 23rd, 2005, 04:59 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You need to get out of the habit of thinking in terms of low-level algorithms, and think instead more functionally. You want the sum of a set of values, and the challenge is to define that set of values.

You haven't said whether you want a 1.0 or a 2.0 solution. I'll assume 2.0 since that's rather easier.

I'm not quite sure what "node1" and "node2" are, but the expression you want is something like this

sum(
  for $x in //node1
  return //node2[dtST ge $x/From and dtET le $x/To]/Time
)

This works as written if your document is validated against a schema to mark the elements as dateTime values. If it isn't you need to cast the values, e.g. xs:dateTime(dtSt) ge xs:dateTime($x/From), and xs:decimal(Time)



Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #3 (permalink)  
Old September 23rd, 2005, 05:36 PM
Authorized User
 
Join Date: Jul 2005
Location: , , .
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hello Michael,

First of all, thank you so much for replying to my message.
I am using 1.0 solution. Is that possible if you can suggest a solution in 1.0 instead. But I am going to try to implement your solution to see if it works.

Basically if you notice my xml, I want to be able to get a result like this:

PERIOD: From="2005-06-06T06:00:00" To="2005-06 06T07:54:37"

DESC START END DURATION
Stopped 06:00:00 06:18:42 00:18:42
             -------------------------------------
              06:19:42 07:19:42 01:00:00
--------------------------------------------------
SubTotal 01:18:42


PERIOD: From="2005-06-06T07:54:37" To="2005-06-06T09:50:56"

DESC START END DURATION
Stopped 07:57:33 08:00:21 00:02:48
             -------------------------------------
              08:07:45 08:17:48 00:10:03
             -------------------------------------
              08:27:44 09:38:53 01:11:09
             -------------------------------------
              09:40:20 09:47:52 00:07:32
--------------------------------------------------
SubTotal 01:31:32

PERIOD: From="2005-06-06T09:50:56" To="2005-06-06T10:00:00"


DESC START END DURATION
Stopped
--------------------------------------------------
SubTotal

Note that, above, there are two PERIODS that have durations and the last one doesn't. What I have above is an example of exactly what I want to do. In my stylesheet I got the individual duration displayed just like the above example but not the SubTotal.

Thanks again and have a great night!

Grace




Reply With Quote
  #4 (permalink)  
Old September 23rd, 2005, 05:42 PM
Authorized User
 
Join Date: Jul 2005
Location: , , .
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Michael,

I forgot to mention this also.

Note that the <Time>1122.0</Time> is the difference between the ST and the ET nodes.
<ST>2005-06-06T06:00:00</ST>
<ET>2005-06-06T06:18:42</ET>
I tried just sum(Time) node if the ST and ET are with the To and From Time.
 <Time From="2005-06-06T06:00:00" To="2005-06-06T07:54:37" TimeId="1">

So there is no need to calculate the differences.

Thanks,
Grace


Reply With Quote
  #5 (permalink)  
Old September 23rd, 2005, 05:45 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

It's still possible to do it using the sum() function in XPath 1.0, because you are summing over numeric values that are actually stored in the nodes. It just becomes a little trickier to select the nodes that you need to sum over. There's no < or > operator on character strings or dates in 1.0, so the usual trick is to strip the punctuation out using translate() and then compare the values as numbers, e.g. 061842 > 060000. There's also no "for" expression, so you have to be a bit more creative with path expressions.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #6 (permalink)  
Old September 26th, 2005, 09:04 AM
Authorized User
 
Join Date: Jul 2005
Location: , , .
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Michael,

In regards to your last respond, I have already gotten that part working already and yes I do use the translate function and then uses
&gt; for >, &lt; for <, &gt;= for >=, and &lt;= for <=. So I do have this part working. All I am having trouble with is my logic to get the sum function to give me the sum of all the <Time> node within the
time PERIOD OF
<Time From="2005-06-06T06:00:00" To="2005-06-06T07:54:37" TimeId="1">
I don't know what else I am missing or it's unable to cache but I can't seem to get it working that's why I have to think or use low-level algorithms in order to explain what I needed to do. My stylesheet report is displayin exactly what I needed but it's just the extra part where I needed it to display the sub total duration for each individual time
[<Time From="2005-06-06T06:00:00" To="2005-06-06T07:54:37" TimeId="1">]

is not working so that's the whole point of my question in this message.

Here is an example of what my condition looks like
<xsl:when test="(translate(translate(translate(ST, '-', ''), 'T', ''), ':', '') &lt;= translate(translate(translate($FromStart, '-', ''), 'T', ''), ':', '')) and (translate(translate(translate(ET, '-', ''), 'T', ''), ':', '') &lt;= translate(translate(translate($ToEnd, '-', ''), 'T', ''), ':', ''))">


I apologize if I confuse you or the readers.

If you can shred some more light on me of how to come about conquering this sum function, please let me know.

Thanks and have a wonderful day,

Grace


Reply With Quote
  #7 (permalink)  
Old September 26th, 2005, 09:30 AM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

First try simplifying this:

Here is an example of what my condition looks like
<xsl:when test="(translate(translate(translate(ST, '-', ''), 'T', ''), ':', '') &lt;= translate(translate(translate($FromStart, '-', ''), 'T', ''), ':', '')) and (translate(translate(translate(ET, '-', ''), 'T', ''), ':', '') &lt;= translate(translate(translate($ToEnd, '-', ''), 'T', ''), ':', ''))">

to this:

<xsl:when test="(translate(ST, '-:T', '') &lt;= translate($FromStart, '-:T, '')) and (translateET, '-:T', '') &lt;= translate($ToEnd, '-:T', ''))">

you could also do the translate on the variables at the time you declare the variables.

You haven't shown me your code so it's difficult to be precise about how you need to change it, but you want some kind of expression like

sum(*[(translate(ST, '-:T', '') &lt;= translate($FromStart, '-:T, '')) and (translateET, '-:T', '') &lt;= translate($ToEnd, '-:T', ''))]/Time)

Much easier in 2.0!


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #8 (permalink)  
Old September 26th, 2005, 09:39 AM
Authorized User
 
Join Date: Jul 2005
Location: , , .
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Michael,

The reason that I haven't show you the actual code is because there is data discretion so all I can do is post a snippet and change the data slightly but the idea is still there. I can send you what I have but is that possible that we do this on a person basis.

Here is my email address: gracehanh@hotmail.com
Can you send me an email there so I can send you the whole report so you can see what I am trying to do.

I am just really stuck and I don't know how else to explain what I need unless you really look at the whole thing.

Could you let me know if you are ok with this.

Thanks,

Grace

Reply With Quote
  #9 (permalink)  
Old September 26th, 2005, 01:18 PM
Authorized User
 
Join Date: Jul 2005
Location: , , .
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Michael,

I have tried using your suggestion and changed my solution from using 2.0 but it still doesn't work.

In my previous tries, I tried using preceeding and following of siblings but it doesn't work either.

I guess what I want to do is be able to cache the previous value and the parse through the next IRD node and if the ST and ET is within the From and To time frame then add (sum()) the value from the <Time> node. But I can't think of any other way that would give me this solution. ghhhhh My head hurts!

Below is the snippet of code that I am using right now to calculate the sub total duration. But this piece of the code is not working right now.

I fixed all of my multiple translate by using the solution that you suggested.

If you can give me some pointers as to where my mistakes are that would be greatly appreciated!

Thanks,

Grace

<xsl:template name="getStoppages">

        <xsl:param name="FromStart"/>
        <xsl:param name="ToEnd"/>
        <xsl:variable name="lblTotalDuration" select="'Total Duration'" />


                    <tr>
                        <td>
                            <xsl:value-of select="$lblTotalDuration"/>
                            </td>
                            <td></td>
                            <td></td>
                            <td align="center">
                                Test<br/>
                                <xsl:for-each select="Node/DT/Inc/IRD">
                                <xsl:choose>
                                    <xsl:when test="(translate(ST, '-:T', '') &lt;= translate($FromStart, '-:T', '') and translate(ET, '-:T', '') &gt;= translate($FromStart, '-:T', '')) or (translate(ST, '-:T', '') &gt;= translate($FromStart, '-:T', '') and translate(ET, '-:T', '') &lt;= translate($ToEnd, '-:T', '')) or (translate(ST, '-:T', '') &lt;= translate($ToEnd, '-:T', '') and translate(ET, '-:T', '') &gt;= translate($ToEnd, '-:T', ''))">
                                        <xsl:variable name = "NextCode" select = "following-sibling::node()[1]/Time"/>
                                        <xsl:choose>
                                            <xsl:when test="(translate(ST, '-:T', '') &lt;= translate($FromStart, '-:T', '')) and translate(ET, '-:T', '') &lt;= translate($ToEnd, '-:T', '')">
                                                <xsl:call-template name="formatTime2">
                                                    <xsl:with-param name="TimeString" select="format-number((sum(Time) -21600), '######0.0')"/>
                                                </xsl:call-template>
                                            </xsl:when>
                                            <xsl:when test="translate(ET, '-:T', '') &gt;= translate($ToEnd, '-:T', '')">
                                                <xsl:call-template name="formatTime2">
                                                    <xsl:with-param name="TimeString" select="format-number((sum(Time)-28800), '######0.0')"/>
                                                </xsl:call-template>
                                            </xsl:when>
                                            <xsl:otherwise>
                                                <xsl:call-template name="formatTime2">
                                                            <xsl:with-param name="TimeString" select="format-number(sum(Time), '######0.0')"/>
                                                        </xsl:call-template>
                                            </xsl:otherwise>
                                        </xsl:choose>

                                    </xsl:when>
                                </xsl:choose>
                            </xsl:for-each>
                        </td>
                    </tr>

</xsl:template>


Reply With Quote
  #10 (permalink)  
Old September 26th, 2005, 01:37 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You're still talking of sequential processing: "and then add...". I'm clearly not getting through to you. Don't think about this sequentially. Select the nodes you want to total over using a path expression such as

Node/DT/Inc/IRD[predicate]/Time

and apply the sum() function to this node-set:

sum(Node/DT/Inc/IRD[predicate]/Time)

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
sum and translate in XPath nwright BOOK: XSLT Programmer's Reference, 2nd Edition 2 December 5th, 2008 08:20 AM
sum function pcase XSLT 2 January 2nd, 2008 05:51 PM
Sum function and XPath problems tslag XSLT 2 June 26th, 2006 10:23 AM
SUM Function jmss66 Classic ASP Basics 17 July 29th, 2003 08:00 AM
Need Help with the Sum Function athanatos XSLT 1 July 22nd, 2003 10:06 AM



All times are GMT -4. The time now is 04:04 AM.


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.