1

次のスキーマがあります。

<parent>
  <child id="1" name="Child 1 Version 1" />
</parent>
<parent>
  <child id="2" name="Child 2 Version 1" />
</parent>
<parent>
  <child id="1" name="Child 1 Version 2" />
</parent>

各 ID の最後のノードのみを処理したい。以下は、いくつかの読書に基づいて試したことです。

  <xsl:for-each select="//parent/child">
    <xsl:sort select="@id"/>
    <xsl:if test="not(@id=following-sibling::*/@id)">
      <xsl:element name="child">
        <xsl:value-of select="@name"/>
      </xsl:element>
    </xsl:if>
  </xsl:for-each>

しかし、うまくいかないようです。私の出力には、まだ 3 つの要素がすべて含まれています。問題を修正するために何ができるかについてのアイデアはありますか?

4

2 に答える 2

2

各IDの最後のノードのみを処理したい。以下は、いくつかの読書に基づいて試したことです。

  <xsl:for-each select="//parent/child"> 
    <xsl:sort select="@id"/> 
    <xsl:if test="not(@id=following-sibling::*/@id)"> 
      <xsl:element name="child"> 
        <xsl:value-of select="@name"/> 
      </xsl:element> 
    </xsl:if> 
  </xsl:for-each> 

しかし、うまくいかないようです。私の出力には、まだ 3 つの要素がすべて含まれています。問題を修正するために何ができるかについてのアイデアはありますか?

このコードの問題は、ノードがソートされたノードセットに含まれていても、それらfollowing-siblingの s がドキュメント内にあることです。

このコードを機能させるには、最初に、ノードが目的の方法でソートされたまったく新しいドキュメントを作成します。次に、(XSLT 1.0 ではxxx:node-set()、生成された RTF で拡張機能を使用して、通常の XML ドキュメントにする必要があります。 ) このドキュメントでは、ノードは必要に応じて兄弟を持っています。

解決策:

この変換は、拡張関数の使用を必要としない 1 つの考えられる XSLT 1.0 ソリューションを示しています。

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

 <xsl:key name="kchildById" match="child" use="@id"/>

 <xsl:template match="/*">
  <t>
    <xsl:apply-templates select=
    "*/child[generate-id()
            =
             generate-id(key('kchildById',
                             @id)[last()]
                         )
            ]
    "/>
  </t>
 </xsl:template>

 <xsl:template match="child">
  <child>
   <xsl:value-of select="@name"/>
  </child>
 </xsl:template>
</xsl:stylesheet>

提供された XML フラグメントに適用された場合(最上位の要素にラップされて整形式の XML ドキュメントになり、 の 2 番目のバージョンが追加されますid="2"):

<t>
    <parent>
        <child id="1" name="Child 1 Version 1" />
    </parent>
    <parent>
        <child id="2" name="Child 2 Version 1" />
    </parent>
    <parent>
        <child id="1" name="Child 1 Version 2" />
    </parent>
    <parent>
        <child id="2" name="Child 2 Version 2" />
    </parent>
</t>

必要な結果を生成します:

<t>
   <child>Child 1 Version 2</child>
   <child>Child 2 Version 2</child>
</t>

: グループ化に Muenchian メソッドを使用する。

于 2010-10-21T01:34:06.060 に答える
1

このスタイルシート:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kParentByChildId" match="parent" use="child/@id"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="parent[count(.|key('kParentByChildId',
                                            child/@id)[last()]) != 1]"/>
</xsl:stylesheet>

出力:

<root>
    <parent>
        <child id="2" name="Child 2 Version 1"></child>
    </parent>
    <parent>
        <child id="1" name="Child 1 Version 2"></child>
    </parent>
</root>

。@idでグループ化し、グループの最後を選択します。

編集:これが混乱する場合に備えて。上記のスタイルシートの意味:同じ種類の最後のものを持たないものを実行するすべてのものをコピーしますchild@id。したがって、グループの最後を選択するのではなく、逆論理として、ストライピングはグループの最後ではありません。

2番。なぜあなたは機能していないのですか?まあ、following-sibling軸のため。最初の種類を見つけるためのあなたの方法は、キーを実装するプロセッサがほとんどなかった昔からのものです。今、それらの時代は過ぎ去りました。

したがって、このスタイルシート:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:template match="t">
        <xsl:for-each select="parent/child">
            <xsl:sort select="@id"/>
            <xsl:if test="not(@id=following::child/@id)">
                <xsl:element name="child">
                    <xsl:value-of select="@name"/>
                </xsl:element>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

出力:

<child>Child 1 Version 2</child>
<child>Child 2 Version 1</child>

:要素には兄弟がないfollowingため、軸。child

于 2010-10-20T20:55:35.387 に答える