472,801 Members | 1,266 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,801 software developers and data experts.

[XSLT] averaging

I have the following XML file (simplified from the actual):

<r>
<o><n>1</n><si>s</si><v1>1</v1><v2>2</v2><v3>3</v3></o>
<o><n>2</n><si>i</si><v1>4</v1><v2>5</v2><v3>6</v3></o>
<o><n>3</n><si>s</si><v1>7</v1><v2>8</v2><v3>9</v3></o>
<o><n>5</n><si>i</si><v1>10</v1><v2>11</v2><v3>12</v3></o>
<o><n>6</n><si>i</si><v1>13</v1><v2>14</v2><v3>15</v3></o>
</r>

and the following stylesheet (again simplified):
<xsl:template match="/"><html><body><table>
<xsl:for-each select="r/o"><tr>
<td><xsl:value-of select="n" /></td>
<td><xsl:value-of select="si" /></td>
<td><xsl:value-of select="v1" /></td>
<td><xsl:value-of select="v2" /></td>
<td><xsl:value-of select="v3" /></td>
<td><xsl:value-of
select="(v1 + (2 * v2) + (3 * v3)) div (v1 + v2 + v3)" /></td>
</tr></xsl:for-each>
<tfoot>
<tr><th scope="row" colspan="5">Average when "s"</th>
<td> [...] </td></tr>
<tr><th scope="row" colspan="5">Average when "i"</th>
<td> [...] </td></tr></tfoot></table></body></html>

In place of the '[...]' I wish to have the weighted averages, as follows.
In place of the first '[...]' I want
( 1 + 2*2 + 3*3 + 7 + 2*8 + 3*9 ) / ( 1 + 2 + 3 + 7 + 8 + 9 )
(which is the same as the weighted average of the various weighted
averages already computed), and in place of the second '[...]' I want
( 4 + 2*5 + 3*6 + 10 + 2*11 + 3*12 + 13 + 2*14 + 3* 15 ) divided
by ( 4+ 5+ 6+ 10 + 11 + 12 + 13 + 14 + 15 ).

Is there a way to do this in XSLT?

Thanks,

Michael Hamm It's not who you know, it's whom.
AM, Math, Wash. U. St. Louis Joan Rivers
ms****@math.wustl.edu Fine print:
http://www.math.wustl.edu/~msh210/ ... legal.html
Dec 28 '05 #1
2 1777
Michael Hamm wrote:

In place of the '[...]' I wish to have the weighted averages, as follows.
In place of the first '[...]' I want
( 1 + 2*2 + 3*3 + 7 + 2*8 + 3*9 ) / ( 1 + 2 + 3 + 7 + 8 + 9 )
(which is the same as the weighted average of the various weighted
averages already computed), and in place of the second '[...]' I want
( 4 + 2*5 + 3*6 + 10 + 2*11 + 3*12 + 13 + 2*14 + 3* 15 ) divided
by ( 4+ 5+ 6+ 10 + 11 + 12 + 13 + 14 + 15 ).

Is there a way to do this in XSLT?
Sure. One way to do it directly is this:

<xsl:value-of
select="(sum(o[si='s']/v1)+2*sum(o[si='s']/v2)+3*sum(o[si='s']/v3)) div
(sum(o[si='s']/v1)+sum(o[si='s']/v2)+sum(o[si='s']/v3))"/>

That works, but it has some limitations. First, it's very long and hard
to read. Second, you have to redo the entire calculation for [si='i']
which is a maintenance problem. Third, if you ever need to change the
calculation, you'll have to change it in multiple places, which is
another maintenance problem. A better strategy is to separate the
selection from the calculation, and the way to do that is to use templates.

Also, I notice that you use xsl:for-each in your example where
xsl:apply-templates would be a better choice. Early on when I was
learning XSLT, it became clear to me that whenever I found myself using
xsl:for-each, it was probably better done using xsl:apply-templates.

I wrote a new XSLT which is longer, but it has the advantage that it
doesn't have the limitations mentioned above.

Note that the calculations use recursion, which is the usual way to get
things done in XSLT. You'll find it useful as you create more complex
calculations in XSLT.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

<xsl:output method="html" indent="yes" />
<xsl:template match="r">
<html>
<body>
<table>
<thead>
<tr>
<th>n</th>
<th>si</th>
<th>v1</th>
<th>v2</th>
<th>v3</th>
<th>calculation</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="o" />
</tbody>
<tfoot>
<tr>
<th scope="row" colspan="5">Average when "s"</th>
<td><xsl:call-template name="avg">
<xsl:with-param name="list" select="o[si='s']"/>
</xsl:call-template></td>
</tr>
<tr>
<th scope="row" colspan="5">Average when "i"</th>
<td><xsl:call-template name="avg">
<xsl:with-param name="list" select="o[si='i']"/>
</xsl:call-template></td>
</tr>
</tfoot>
</table>
</body>
</html>
</xsl:template>

<xsl:template match="o">
<tr>
<td><xsl:value-of select="n" /></td>
<td><xsl:value-of select="si" /></td>
<td><xsl:value-of select="v1" /></td>
<td><xsl:value-of select="v2" /></td>
<td><xsl:value-of select="v3" /></td>
<td><xsl:call-template name="avg">
<xsl:with-param name="list" select="."/>
</xsl:call-template></td>
</tr>
</xsl:template>

<xsl:template match="o" mode="calcnum">
<xsl:value-of select="(v1 + (2 * v2) + (3 * v3))"/>
</xsl:template>

<xsl:template match="o" mode="calcdenom">
<xsl:value-of select="(v1 + v2 + v3)" />
</xsl:template>

<xsl:template name="avg">
<xsl:param name="list"/>
<xsl:variable name="num">
<xsl:call-template name="numerator">
<xsl:with-param name="list" select="$list"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="denom">
<xsl:call-template name="denominator">
<xsl:with-param name="list" select="$list"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$num div $denom"/>
</xsl:template>

<xsl:template name="numerator">
<xsl:param name="list"/>
<xsl:choose>
<xsl:when test="$list">
<xsl:variable name="first">
<xsl:apply-templates select="$list[1]" mode="calcnum"/>
</xsl:variable>
<xsl:variable name="rest">
<xsl:call-template name="numerator">
<xsl:with-param name="list" select="$list[position()!=1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$first + $rest"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template name="denominator">
<xsl:param name="list"/>
<xsl:choose>
<xsl:when test="$list">
<xsl:variable name="first">
<xsl:apply-templates select="$list[1]" mode="calcdenom"/>
</xsl:variable>
<xsl:variable name="rest">
<xsl:call-template name="denominator">
<xsl:with-param name="list" select="$list[position()!=1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$first + $rest"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
For completeness, here's your original data file:

<?xml version="1.0"?>
<r>
<o><n>1</n><si>s</si><v1>1</v1><v2>2</v2><v3>3</v3></o>
<o><n>2</n><si>i</si><v1>4</v1><v2>5</v2><v3>6</v3></o>
<o><n>3</n><si>s</si><v1>7</v1><v2>8</v2><v3>9</v3></o>
<o><n>5</n><si>i</si><v1>10</v1><v2>11</v2><v3>12</v3></o>
<o><n>6</n><si>i</si><v1>13</v1><v2>14</v2><v3>15</v3></o>
</r>

Ed
Dec 30 '05 #2
On Fri, 30 Dec 2005, Ed Beroset wrote, in small part:
Sure.


Wow. Thanks so much for your response -- beyond the call of, Usenet duty.
Or whatever. Anyway, thanks a lot.

Happy new year,

Michael Hamm It's not who you know, it's whom.
AM, Math, Wash. U. St. Louis Joan Rivers
ms****@math.wustl.edu Fine print:
http://www.math.wustl.edu/~msh210/ ... legal.html
Jan 2 '06 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: ted | last post by:
Was wondering if XSLT alone is appropriate for the following situation. From XML, I'm creating a small website (around 50 pages) with pages that link to each other through a nav menu and a...
1
by: Mohit | last post by:
Hi Friends I have to call 1 of the 2 child XSLT files from the Main XSLT file based on some criteria. I want one child XSLT file will be executed by version 1 of XSLT processor and the other by...
3
by: Teksure | last post by:
Hi group, searching in the Internet I found two products for XML which incorporate a very robust debugger for XSL/XSLT, I would like you to see these products and then, give me your opinion about...
1
by: Rotten Spice | last post by:
Hello all, I am still pretty new to Access but I do have a grasp on some basic functions. I am having a problem with averaging and I think I'm trying to do something a little too complex and...
1
by: Sergey Dubinets | last post by:
In effort to prioritize our goals we composed the list of random features each of them may add value to set of XSLT tools offered from Microsoft. 1. XSLTc (Compiler for XSLT...
12
by: Chris | last post by:
Hi, Just wondering if anyone out there knows if it is possible to convert a CSV to xml using XSLT? I've seen a lot of examples of xml to CSV, but is it possible to go back the other way? I...
1
by: JJ R | last post by:
I am trying to develop a simple and efficient to calculate averages. For example I want to calculate the averages of the Values for rows 1 and 2 and use ID 1 as the row with the average result. ...
2
jkmyoung
by: jkmyoung | last post by:
Here's a short list of useful xslt general tricks that aren't taught at w3schools. Attribute Value Template Official W3C explanation and example This is when you want to put dynamic values...
1
by: Kid Programmer | last post by:
Hello guys. Whenever I am learning a new programming language I like to learn the basics (variables, loops, conditionals etc) by writing a program that will calculate averages. I wrote a simple...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
How does React native implement an English player?
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.