1

xslt group-by で学習しています。以下のようなサンプルxmlがあります

<?xml version="1.0" encoding="UTF-8"?>
<h1>
    <a1>abcd</a1>
    <a2>efgh</a2>
    <h2>
        <b1>IV-3</b1>
        <b2>20.00</b2>
        <h3>
            <c1>VCH</c1>
            <c2>1001</c2>
            <c3>100.00</c3>
        </h3>
    </h2>
    <h2>
        <b1>IV-3</b1>
        <b2>50.00</b2>      
    </h2>   
    <h2>
        <b1>IV-3</b1>
        <b2>10.00</b2>
        <h3>
            <c1>VCH</c1>
            <c2>1001</c2>
            <c3>300.00</c3>
        </h3>
    </h2>
    <h2>
        <b1>IV-3</b1>
        <b2>30.00</b2>      
    </h2>
</h1>

最初に b1 値でグループ化し、b2 値を合計する必要があります。h3 ノードが存在する場合は、c2 でグループ化し、そのグループの c3 値を合計する必要があります。私のxsltは以下の通りです。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="h1">
        <t1>
            <d1>
                <xsl:value-of select="a1"/>
            </d1>
            <d2>
                <xsl:value-of select="a2"/>
            </d2>
            <xsl:for-each-group select="h2" group-by="b1">
                <xsl:if test="current-group()/count(h3) > 0 ">
                    <xsl:for-each-group select="current-group()/h3" group-by="c2">
                        <t2>
                            <e1>
                                <xsl:value-of select="../b1"/>
                            </e1>
                            <e2>
                                <xsl:value-of select="format-number(sum(current-group()/../b2),'#.00')"/>
                            </e2>
                            <e3>
                            <xsl:value-of select="format-number(sum(current-group()/c3),'#.00')"/>
                            </e3>
                        </t2>
                    </xsl:for-each-group>
                </xsl:if>
                <xsl:if test="current-group()/count(h3) = 0 ">                  
                        <t2>
                            <e1>
                                <xsl:value-of select="b1"/>
                            </e1>
                            <e2>
                                <xsl:value-of select="format-number(sum(current-group()/b2),'#.00')"/>
                            </e2>
                            <e3>
                            <xsl:value-of select="11111"/>
                            </e3>
                        </t2>
                </xsl:if>
            </xsl:for-each-group>
        </t1>
    </xsl:template>
</xsl:stylesheet>

h3 が存在しない場合、e2 に対して取得している集計値は正しくありません。期待される結果は

<?xml version="1.0" encoding="UTF-8"?>
<t1 xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <d1>abcd</d1>
    <d2>efgh</d2>
    <t2>
        <e1>IV-3</e1>
        <e2>30.00</e2>
        <e3>400.00</e3>
    </t2>
    <t2>
        <e1>IV-3</e1>
        <e2>80.00</e2>
        <e3>11111</e3>
    </t2>
</t1>

助けてくれてありがとう!

4

1 に答える 1

0

一度に 2 つの値をグループ化したいので、group-byセレクターを変更する必要があります。

から

<xsl:for-each-group select="h2" group-by="b1">

<xsl:for-each-group select="h2" group-by="concat(b1, '|', boolean(h3))">

それとは別に、コードは機能します。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
  <xsl:template match="h1">
    <t1>
      <d1>
        <xsl:value-of select="a1" />
      </d1>
      <d2>
        <xsl:value-of select="a2" />
      </d2>
      <xsl:for-each-group select="h2" group-by="concat(b1, '|', boolean(h3))">
        <xsl:if test="current-group()/h3">
          <xsl:for-each-group select="current-group()/h3" group-by="c2">
            <t2>
              <e1>
                <xsl:value-of select="../b1" />
              </e1>
              <e2>
                <xsl:value-of select="format-number(sum(current-group()/../b2), '#.00')" />
              </e2>
              <e3>
                <xsl:value-of select="format-number(sum(current-group()/c3), '#.00')" />
              </e3>
            </t2>
          </xsl:for-each-group>
        </xsl:if>
        <xsl:if test="not(current-group()/h3)">
          <t2>
            <e1>
              <xsl:value-of select="b1" />
            </e1>
            <e2>
              <xsl:value-of select="format-number(sum(current-group()/b2), '#.00')" />
            </e2>
            <e3>
              <xsl:value-of select="11111" />
            </e3>
          </t2>
        </xsl:if>
      </xsl:for-each-group>
    </t1>
  </xsl:template>
</xsl:stylesheet>

このスタイルシートは、必要な出力を生成します

<t1 xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
   <d1>abcd</d1>
   <d2>efgh</d2>
   <t2>
      <e1>IV-3</e1>
      <e2>30.00</e2>
      <e3>400.00</e3>
   </t2>
   <t2>
      <e1>IV-3</e1>
      <e2>80.00</e2>
      <e3>11111</e3>
   </t2>
</t1>

ノート

  • boolean(h3)文字列を放出する'true'か、要素'false'の存在に応じて<h3>
  • 同様に、テストはそれぞれおよびに<xsl:if>簡略化できます(空のノード セットは に評価されます) 。current-group()/h3not(current-group()/h3)false
  • exclude-result-prefixes="xs fn"出力ドキュメントから不要な名前空間宣言を削除するように宣言する必要があります。
于 2013-09-09T20:35:53.220 に答える