如何使用xsl获取xml数据的平均值

时间:2013-01-30 14:52:07

标签: xslt

我想获得以下内容的平均值

 <SectorWeightings Currency="xxx">
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="A B||16.324500000000" Date="8/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="C||16.744400000000" Date="7/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="C S||10.177400000000" Date="8/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="C S||8.8950000000000" Date="7/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="E||12.841600000000" Date="8/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="E||13.551700000000" Date="7/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="Fi S||14.157900000000" Date="8/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="Fi S||15.221200000000" Date="7/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="H Care||12.508900000000" Date="7/31/2011" />
      <SectorWeightingsEntry Type="Sector Name||Sector Weight (%)" Value="H Care||13.198200000000" Date="8/31/2011" />
 </SectorWeightings>  

作为前5行数值中的示例并计算平均值。

这是改进的代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

  <xsl:template match="/">
    <html>
      <body>
        <h2> zzzzzzzzz  </h2>

        <table style="width:50%;font-size:12px;" cellspacing="0" cellpadding="0">
          <tr style="width:50%; text-align:left;background-color:E6F1F9;">
            <th>    xxxxx   </th>
            <th>    yyyyy     </th>
          </tr>

          <xsl:apply-templates
            select="FundPricePerf/Group[@Name='xxxxx']/SubGroup[@Name='S']
                    /Fund[@FundCode='vv']/SectorWeightings
                    /SectorWeightingsEntry[@Type='Sector Name||Sector Weight (%)']">
            <xsl:sort select="substring-after('||', @Value)" data-type="number"
                      order="descending" />
          </xsl:apply-templates>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="SectorWeightingsEntry">
   <xsl:if test="position() &lt;= 5">
    <tr>
      <td>
        <xsl:value-of select="format-number(substring-after(@Value, '||'), '#.#')"/>
      </td>
    </tr>
   </xsl:if>
  </xsl:template>

</xsl:stylesheet>

有人可以帮我计算平均值吗?我需要继续上面的代码。

2 个答案:

答案 0 :(得分:3)

您可以像sum()divcount()那样使用...

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  xmlns:so="http://stackoverflow.com/questions/14606819"
  exclude-result-prefixes="xsl exsl so">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/">
  <average>
    <xsl:variable name="weights">
      <xsl:apply-templates select="*/SectorWeightingsEntry/@Value" mode="extract-weight" />
    </xsl:variable> 
    <xsl:variable name="w" select="exsl:node-set($weights)/so:weight" />
    <xsl:value-of select="sum( $w) div count( $w)" />
  </average>
</xsl:template>

<xsl:template match="@Value" mode="extract-weight">
  <so:weight>
    <xsl:value-of select="substring-after(.,'||')" />
  </so:weight>
</xsl:template>

</xsl:stylesheet>

这会产生......

<average>13.362079999999997</average>

答案 1 :(得分:1)

请试一试:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

  <xsl:template match="/">
    <xsl:variable name="items"
            select="FundPricePerf/Group[@Name='xxxxx']/SubGroup[@Name='S']
                    /Fund[@FundCode='vv']/SectorWeightings
                    /SectorWeightingsEntry[@Type='Sector Name||Sector Weight (%)']" />
    <html>
      <body>
        <h2> zzzzzzzzz  </h2>

        <table style="width:50%;font-size:12px;" cellspacing="0" cellpadding="0">
          <tr style="width:50%; text-align:left;background-color:E6F1F9;">
            <th>    xxxxx   </th>
            <th>    yyyyy     </th>
          </tr>

          <xsl:apply-templates select="$items">
            <xsl:sort select="substring-after(@Value, '||')" data-type="number"
                      order="descending" />
          </xsl:apply-templates>
        </table>

        <xsl:call-template name="ShowAverage">
          <xsl:with-param name="items" select="$items" />
        </xsl:call-template>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="SectorWeightingsEntry">
    <xsl:if test="position() &lt;= 5">
      <tr>
        <td>
          <xsl:value-of select="format-number(substring-after(@Value, '||'), '#.#')"/>
        </td>
      </tr>
    </xsl:if>
  </xsl:template>

  <xsl:template name="ShowAverage">
    <xsl:param name="items" />

    <xsl:variable name="sumTopItems">
      <xsl:choose>
        <xsl:when test="$items">
          <xsl:apply-templates select="$items" mode="sumItems">
            <xsl:with-param name="items" select="$items" />
            <xsl:sort select="substring-after(@Value, '||')" data-type="number"
                      order="descending" />
          </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="itemsToAvg"
                  select="5 * (count($items) >= 5 or not($items)) + 
                              count($items) * (count($items) &lt; 5)" />

    <xsl:value-of select="concat('Average: ', 
                  format-number($sumTopItems div $itemsToAvg, '#.#'))"/>
  </xsl:template>

  <xsl:template match="SectorWeightingsEntry" mode="sumItems">
    <xsl:param name="items" />
    <xsl:param name="limit" select="5" />
    <xsl:param name="tally" select="0" />

    <xsl:if test="position() = 1">
      <xsl:if test="$limit &lt;= 0">
        <xsl:value-of select="$tally"/>
      </xsl:if>
      <xsl:if test="$limit > 0">
        <xsl:variable name="remaining"
                      select="$items[generate-id(.) != generate-id(current())]" />
        <xsl:apply-templates select="$remaining" mode="sumItems">
          <xsl:with-param name="items" select="$remaining" />
          <xsl:with-param name="limit" select="$limit - 1" />
          <xsl:with-param name="tally"
                          select="$tally + substring-after(@Value, '||')" />
          <xsl:sort select="substring-after(@Value, '||')" data-type="number"
                    order="descending" />
        </xsl:apply-templates>
      </xsl:if>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

在示例XML上运行时的输出:

<html>
  <body>
    <h2> zzzzzzzzz  </h2>
    <table style="width:50%;font-size:12px;" cellspacing="0" cellpadding="0">
      <tr style="width:50%; text-align:left;background-color:E6F1F9;">
        <th>    xxxxx   </th>
        <th>    yyyyy     </th>
      </tr>
      <tr>
        <td>16.7</td>
      </tr>
      <tr>
        <td>16.3</td>
      </tr>
      <tr>
        <td>15.2</td>
      </tr>
      <tr>
        <td>14.2</td>
      </tr>
      <tr>
        <td>13.6</td>
      </tr>
    </table>Average: 15.2</body>
</html>