开发者

Can I perform elementwise division in XSLT?

开发者 https://www.devze.com 2022-12-19 15:47 出处:网络
I have a data structure which looks something like: <resultSet> <result> <numCorrec开发者_StackOverflow中文版t>1</numCorrect>

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

精彩评论

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

关注公众号