xml XSLT 中的算术运算

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3389089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 13:13:30  来源:igfitidea点击:

arithmetic operation in XSLT

xmlxslt

提问by brainless

How can I find the greatest 2 numbers out of 3 numbers and perform some arithmetic operations on them like in following example?

如何从 3 个数字中找到最大的 2 个数字并对它们执行一些算术运算,如下例所示?

<root>
    <num>10</num>
    <num>12</num>
    <num>8</num>
</root>

For the above input the xslt code should display "10 + 12 = 22" and "average = 11".

对于上述输入,xslt 代码应显示“10 + 12 = 22”和“average = 11”。

回答by

This stylesheet:

这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/root">
        <xsl:variable name="max1" select="num[not(../num > .)]"/>
        <xsl:variable name="max2" select="num[not(../num[count(.|$max1)!=1] > .)]"/>
        <xsl:value-of select="concat($max1,' + ',
                                     $max2,' = ',
                                     $max1 + $max2,'&#xA;',
                                     'average = ',
                                     ($max1 + $max2) div 2,'&#xA;')"/>
    </xsl:template>
</xsl:stylesheet>

Output:

输出:

12 + 10 = 22
average = 11

回答by Dimitre Novatchev

I. XSLT 1.0 solution

一、XSLT 1.0解决方案

This transformation finds the sum and average of all numbers except those with the minimal value-- works for a nodeset of numbers of any length:

此转换查找除具有最小值的数字之外的所有数字的总和和平均值——适用于任何长度的数字节点集:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:variable name="vMin">
  <xsl:for-each select="/*/num">
   <xsl:sort data-type="number"/>
   <xsl:if test="position()=1">
    <xsl:value-of select="."/>
   </xsl:if>
  </xsl:for-each>
 </xsl:variable>

 <xsl:variable name="vNumsWithoutMin" select="/*/num[not(.=$vMin)]"/>

 <xsl:variable name="vSumWithoutMin" select="sum($vNumsWithoutMin)"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="$vNumsWithoutMin"/>
  <xsl:value-of select="concat(' = ', $vSumWithoutMin)"/>
  average = <xsl:value-of select=
  "$vSumWithoutMin div count($vNumsWithoutMin)"/>
 </xsl:template>

 <xsl:template match="num">
   <xsl:value-of select="."/>
   <xsl:if test="not(position()=last())">
     <xsl:text> + </xsl:text>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

When this is applied on the provided XML document:

当这应用于提供的 XML 文档时

<root>
    <num>10</num>
    <num>12</num>
    <num>8</num>
</root>

the wanted, correct result is produced:

产生了想要的、正确的结果

10 + 12 = 22
average = 11

II. XSLT 2.0 solution

二、XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output method="text"/>

 <xsl:variable name="vMin" select="min(/*/num/number(.))"/>

 <xsl:variable name="vNumsSansMin"
  select="/*/num[not(number() eq $vMin)]/number(.)"/>
 <xsl:variable name="vAvgSansMin"
      select="avg($vNumsSansMin)"/>

 <xsl:template match="/*">
    <xsl:sequence select=
     "(for $i in 1 to count($vNumsSansMin)
        return
         ($vNumsSansMin[$i],
          if(not($i eq count($vNumsSansMin)))
            then ' + '
            else ()
          )
      ),
      ' = ', sum($vNumsSansMin)
     "/>

     average = <xsl:sequence select="$vAvgSansMin"/>
 </xsl:template>
</xsl:stylesheet>