2

以下是我的代码的简短示例。

我想计算组(或 gid)中每个条目的平均target_value在一个简单的伪代码中,这将按以下方式编写:

total target_value of entries with gid "001" / amount of entries with gid "001"

但是,由于 XML 对我来说相当新,我想知道如何重用已经计算的值(请参阅下面的 XSL)以进行进一步的计算?变量是最有效的方法吗?如果是,应该在哪里/如何定义它们?

XML:

<root>
   <entry gid ="001">
      <level_1>
         <target_value>50</target_value>
      </level_1>
   </entry>

   <entry gid ="001">
      <level_1>
         <target_value>30</target_value>
      </level_1>
   </entry>
</root>

XSL:

<xsl:value-of select="sum(entry[@gid='001']/level_1/target_value)" />

结果:80

任何帮助将不胜感激!

4

4 回答 4

0
<xsl:value-of select="
  sum(entry[@gid='001']/level_1/target_value) div count(entry[@gid='001'])
" />

当然,您可以将计算值保存在变量中以供重复使用:

<xsl:variable 
  name="target_value_sum" 
  select="sum(entry[@gid='001']/level_1/target_value)" 
/>

<xsl:value-of select="$target_value_sum div count(entry[@gid='001'])" />

在这种情况下没有必要。

于 2012-05-22T15:18:30.173 回答
0

这个 xslt 1.0 样式表...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

  <xsl:key name="entry-by-gid" match="entry" use="@gid" />

  <xsl:template match="root">
   <entries>
    <xsl:apply-templates select="entry
       [generate-id(.) = generate-id( key('entry-by-gid',@gid)[1])]"/>
   </entries>
   </xsl:template>

  <xsl:template match="entry">
    <entry-average gid="{@gid}">
      <xsl:value-of select="sum(../entry[@gid=current()/@gid]/level_1/target_value) div
                          count(../entry[@gid=current()/@gid]/level_1/target_value)"/>
    </entry-average>
  </xsl:template>

</xsl:stylesheet>

会产生像..这样的输出

<?xml version="1.0" encoding="utf-8"?>
<entries>
  <entry-average gid="001">40</entry-average>
</entries>

对于 xslt 2.0,使用 for-each-group。这是一个 XSLT 2.0 样式表来做同样的事情。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
   <entries>
    <xsl:for-each-group select="*/entry" group-by="@gid">
      <entry-average gid="{@gid}">
        <xsl:value-of select="sum(../entry[@gid=current-grouping-key()]/level_1/target_value) div
                            count(../entry[@gid=current-grouping-key()]/level_1/target_value)"/>
      </entry-average>
    </xsl:for-each-group>
   </entries>
 </xsl:template>

</xsl:stylesheet>
于 2012-05-22T15:45:55.660 回答
0

我会把它写成两个文件范围的变量,第一个选择节点集到一个变量中,第二个计算平均值。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output method="text" />

  <xsl:variable name="target_values" select="/root/entry[@gid='001']/level_1/target_value" />
  <xsl:variable name="mean_target_values" select="sum($target_values) div count($target_values)" />

  <xsl:template match="/root">
    <xsl:value-of select="format-number($mean_target_values, '0.00')" />
  </xsl:template>

</xsl:stylesheet>

由于您提到格式化浮点数,我已对其进行了修改以使用该format-number函数。格式符号与 Java DecimalForamt 类的相同,文档在此处。我使用0.00了它给出了两位小数。我认为如果需要,如何更改它很清楚。

于 2012-05-22T16:05:56.583 回答
0

看到您的评论后,您想为所有条目组提供相同的信息,@gid我必须编写一个与我以前的解决方案截然不同的解决方案,它值得一个新的答案。

不幸的是,以这种方式分组并不是 XSL 中最简单的部分,但它就是这样。请注意,使用所谓的 Muenchian 方法可以提高效率,但我以这种方式编写它是为了(相对)简单性和可读性。(我看到Sean B. Durkin使用了更快的方法,因此您可以比较它们。)

它的工作方式是xsl:for-each循环遍历<entry>具有gid与所有先前元素不同的属性的所有<entry>元素。这会选择gid属性的所有唯一值,这些值会复制到$gid变量中。

之后,将<target_value>元素内<entry>具有相同gid属性的所有元素收集到一个节点集中并分配给变量$target_values。之后很容易计算它们并找到它们的总数,将它们除以另一个以获得平均值,然后将其分配给另一个变量。

然后只输出gid每个不同的属性值和平均值gid。该$nl变量是一个方便变量,等于用于布局输出的换行符。

我希望很容易从这里推断出您需要的最终解决方案。如果你卡住了,请再次询问。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output method="text" />

  <xsl:variable name="nl">
    <xsl:text>
</xsl:text>
  </xsl:variable>

  <xsl:template match="/root">
    <xsl:for-each select="entry[not(@gid = preceding-sibling::entry/@gid)]">
      <xsl:sort select="@gid" />

      <xsl:variable name="gid" select="@gid" />

      <xsl:variable name="target_values" select="/root/entry[@gid=$gid]/level_1/target_value" />
      <xsl:variable name="mean_target_values" select="sum($target_values) div count($target_values)" />

      <xsl:value-of select="concat('GID: ', $gid, $nl)" />
      <xsl:value-of select="concat('mean target value ', format-number($mean_target_values, '0.00'), $nl)" />
      <xsl:value-of select="$nl" />

    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

产生这个输出

GID: 001
mean target value 40.00

GID: 002
mean target value 60.33

GID: 003
mean target value 27.00

应用于此 XML 时

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <entry gid ="001">
        <level_1>
            <target_value>50</target_value>
        </level_1>
    </entry>
    <entry gid ="001">
        <level_1>
            <target_value>30</target_value>
        </level_1>
    </entry>
    <entry gid ="002">
        <level_1>
            <target_value>40</target_value>
        </level_1>
    </entry>
    <entry gid ="002">
        <level_1>
            <target_value>72</target_value>
        </level_1>
    </entry>
    <entry gid ="002">
        <level_1>
            <target_value>69</target_value>
        </level_1>
    </entry>
    <entry gid ="003">
        <level_1>
            <target_value>14</target_value>
        </level_1>
    </entry>
    <entry gid ="003">
        <level_1>
            <target_value>44</target_value>
        </level_1>
    </entry>
    <entry gid ="003">
        <level_1>
            <target_value>23</target_value>
        </level_1>
    </entry>
</root>
于 2012-05-22T17:18:23.100 回答