开发者

Can I perform elementwise division in XSLT?

I have a data structure which looks something like:

<resultSet>
  <result>
    <numCorrec开发者_StackOverflow中文版t>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.


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..


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜