Reputation: 77074
I have a data structure which looks something like:
<resultSet>
<result>
<numCorrect>1</numCorrect>
<truthCorrect>4</truthCorrect>
</result>
<result>
<numCorrect>2</numCorrect>
<truthCorrect>4</truthCorrect>
</result>
<result>
<numCorrect>3</numCorrect>
<truthCorrect>5</truthCorrect>
</result>
<result>
<numCorrect>5</numCorrect>
<truthCorrect>6</truthCorrect>
</result>
</resultSet>
I'd like to compute avg((result/numCorrect) div (result/truthCorrect))
, but XSLT doesn't seem to allow element-wise division, how do I compute this average?
If it helps, I'm using Saxon as an XSLT 2.0 processor.
Upvotes: 4
Views: 4557
Reputation: 77074
A short-form solution that works seems to be this:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common">
<xsl:template match="/resultSet">
<xsl:variable name="foo">
<xsl:for-each select="result">
<n><xsl:value-of select="numCorrect div truthCorrect" /></n>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="avg(exslt:node-set($foo)/n)" />
</xsl:template>
</xsl:stylesheet>
where <xsl:value-of select="avg(exslt:node-set($foo)/n)" />
may be replaced with
<xsl:value-of select="sum(exslt:node-set($foo)/n) div count(result)" />
if you're using an XSLT engine that supports exslt extensions but doesn't have the non-standard avg
function.
Upvotes: 1
Reputation: 196177
The following will do what you want ..
It uses recursion and serially adds all paired calculation and at the end divides by the number of results..
<xsl:template match = "/resultSet" >
<xsl:variable name="TotalSum">
<xsl:call-template name="calculator">
<xsl:with-param name="currSum">0</xsl:with-param>
<xsl:with-param name="count"><xsl:value-of select="count(result)"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$TotalSum div count(result)"/>
</xsl:template>
<xsl:template name="calculator">
<xsl:param name="currSum"/>
<xsl:param name="count"/>
<xsl:variable name="actual" select="number(result[number($count)]/numCorrect)"/>
<xsl:variable name="truth" select="number(result[number($count)]/truthCorrect)"/>
<xsl:variable name="singleResult" select="number($actual div $truth)"/>
<xsl:variable name="CycleSum" select="number($currSum + $singleResult)"/>
<xsl:choose>
<xsl:when test="number($count - 1) > 0 ">
<xsl:call-template name="calculator">
<xsl:with-param name="currSum"><xsl:value-of select="$CycleSum"/></xsl:with-param>
<xsl:with-param name="count"><xsl:value-of select="number($count - 1)"/></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$CycleSum"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
Let me know if there are parts you do not understand..
Upvotes: 3