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

同じエントリのすべてのグループにこの情報を提供したいというコメントを見て@gid、以前のソリューションとは非常に異なるソリューションを作成する必要があるため、新しい回答に値します。

残念ながら、この方法でのグループ化は XSL の最も単純な部分ではありませんが、ここにあります。Muenchian 法として知られている方法を使用してより効率的にすることができることに注意してください。( Sean B. Durkinはより高速な方法を使用しているようですので、それらを比較してください。)

これが機能する方法は、先行するすべての要素とは異なる属性を持つxsl:for-eachすべての要素をループすることです。これにより、属性の一意の値がすべて選択され、変数にコピーされます。<entry>gid<entry>gid$gid

その後、同じ属性を持つ<target_value>要素内のすべての要素が nodeset に集められ、 variable に割り当てられます。その後、それらを数えて合計を求め、一方を他方で割って平均を取得し、それを別の変数に代入するのは簡単です。<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 に答える
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

これを 2 つのファイル スコープの変数として記述します。1 つ目はノードセットを変数に選択し、2 つ目は平均を計算します。

<?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小数点以下2桁を与えるものを使用しました。必要に応じて変更する方法は明らかだと思います。

于 2012-05-22T16:05:56.583 に答える