2

等しいノードは、単一のカウンター要素の下にある必要があります。入力:

<Move-Afile>
  <Afile>
    <Item>
    <PACK050>
      <PackNumber>1234</PackNumber>
      </PACK050>
    </Item>
    <Item>
    <PACK050>
      <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
    <Item>
    <PACK050>
      <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
    <Item>
    <PACK050>
      <PackNumber>126</PackNumber>
      </PACK050>
    </Item>
    <Item>
    <PACK050>
      <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
  </Afile>
</Move-Afile>

パック番号ごとにカウンター変数をインクリメントする必要がありますが、ここでは、前の値が現在の値と等しい場合、以下の出力のようにカウンターを無視する必要がある (インクリメントする必要はありません) など、1 つの条件が存在します。以下の出力のようなカウンター。

XSLT テンプレートには、<for-each>次のような構造が含まれている必要があります。

<xsl:template match="/">
  <A>
    <target>
      <xsl:for-each select="/Move-Afile/Afile/Item/PACK050/PackNumber">

        <xsl:variable name="count">
          <!-- get the count here-->
        </xsl:variable>

        <counter>$count</counter>
        <PNumber><xsl:value-of select="."/></PNumber>

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

出力:

<A>
  <target>
    <Item>
    <PACK050>
      <counter>1</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
      <PNumber>1234</PNumber>
      </PACK050>
    </Item>
    <Item
    <PACK050>
      <counter>2</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
      <PNumber>567</PNumber>
      </PACK050>
    </Item>
    <Item><!-- if previous <PackNumber> is  equal to current <PackNumber> ignore the counter -->
      <PACK050>
      <PNumber>567</PNumber>
      </PACK050>
    </Item>
    <Item><!-- if previous <PackNumber> is  equal to current <PackNumber> ignore the counter -->
      <PACK050>
      <PNumber>567</PNumber>
      </PACK050>
    </Item>
    <Item>
    <PACK050>
      <counter>3</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
      <PNumber>126</PNumber>
      </PACK050>
    </Item>

  </target>
</A>
4

2 に答える 2

3

カウンターをインクリメントするものとは考えないでください。同様のノードをグループ化するものと考えてください。ここでやろうとしているのは、Item要素を でグループ化PackNumberし、各グループについて、最初に一致Itemしたcounterものを値で書き、残りを値なしで書き出すことです。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:key name="itemByPnum" match="Item" use="PACK050/PackNumber" />

  <xsl:template match="/">
    <A>
      <target>
        <xsl:apply-templates select="Move-Afile/Afile/Item[generate-id() =
             generate-id(key('itemByPnum', PACK050/PackNumber)[1])]" />
      </target>
    </A>
  </xsl:template>

  <xsl:template match="Item">
    <xsl:apply-templates select="." mode="copy">
      <xsl:with-param name="counter">
        <counter><xsl:value-of select="position()" /></counter>
      </xsl:with-param>
    </xsl:apply-templates>
    <!-- copy without the <counter> all matching Items except the first one -->
    <xsl:apply-templates mode="copy"
          select="key('itemByPnum', PACK050/PackNumber)
          [generate-id() != generate-id(current())]" />
  </xsl:template>

  <xsl:template match="Item" mode="copy">
    <xsl:param name="counter" />
    <Item>
      <PACK050>
        <xsl:copy-of select="$counter" />
        <PNumber><xsl:value-of select="PACK050/PackNumber" /></PNumber>
      </PACK050>
    </Item>
  </xsl:template>
</xsl:stylesheet>

これは Muenchian グループ化と呼ばれる手法の例です。テンプレートのイニシャルapply-templatesは、最初のを eachで/抽出し、テンプレートはそのグループの正しい出力を生成します。 ItemPackNumberItem

于 2013-05-28T16:58:44.563 に答える
2

この問題は、よく知られている XSLT 1.0 の Muenchian Grouping 手法を使用することで実際に解決できます。

この XSLT の場合:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kItemByPackNo" match="Item" use="*/PackNumber"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <A>
      <target>
        <xsl:apply-templates
          select="*/Item[generate-id() = 
                         generate-id(key('kItemByPackNo', */PackNumber)[1])]"/>
      </target>
    </A>
  </xsl:template>

  <xsl:template match="Item">
    <Item>
      <counter>
        <xsl:value-of select="position()"/>
      </counter>
      <xsl:apply-templates/>
    </Item>
    <xsl:copy-of
      select="key('kItemByPackNo', */PackNumber)[
                not(generate-id() = generate-id(current()))
              ]"/>
  </xsl:template>

  <xsl:template match="PackNumber">
    <PNumber>
      <xsl:apply-templates/>
    </PNumber>
  </xsl:template>

</xsl:stylesheet>

...提供された XML に対して適用されます。

<Move-Afile>
  <Afile>
    <Item>
      <PACK050>
        <PackNumber>1234</PackNumber>
      </PACK050>
    </Item>
    <Item>
      <PACK050>
        <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
    <Item>
      <PACK050>
        <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
    <Item>
      <PACK050>
        <PackNumber>126</PackNumber>
      </PACK050>
    </Item>
    <Item>
      <PACK050>
        <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
  </Afile>
</Move-Afile>

...目的の結果が生成されます。

<A>
  <target>
    <Item>
      <counter>1</counter>
      <PACK050>
        <PNumber>1234</PNumber>
      </PACK050>
    </Item>
    <Item>
      <counter>2</counter>
      <PACK050>
        <PNumber>567</PNumber>
      </PACK050>
    </Item>
    <Item>
      <PACK050>
        <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
    <Item>
      <PACK050>
        <PackNumber>567</PackNumber>
      </PACK050>
    </Item>
    <Item>
      <counter>3</counter>
      <PACK050>
        <PNumber>126</PNumber>
      </PACK050>
    </Item>
  </target>
</A>
于 2013-05-28T16:58:06.297 に答える