1

XSLT を使用して属性を介して xml エントリをグループ化する際に問題があります。

ここに私のソースxmlがあります:

<chron>
<chronEntry type="education" order="1" blockorder="1">
    <foo>bar</foo>
</chronEntry>
    <chronEntry type="education" order="2" blockorder="1">
<foo>bar</foo>
    </chronEntry>
<chronEntry type="education" order="3" blockorder="1">
    <foo>bar</foo>
</chronEntry>
<chronEntry type="communityservice" order="1" blockorder="2">
    <foo>bar</foo>
</chronEntry>
<chronEntry type="experience" order="1" blockorder="3">
    <foo>bar</foo>
</chronEntry>
<chronEntry type="experience" order="2" blockorder="3">
    <foo>bar</foo>
</chronEntry>
<chronEntry type="experience" order="3" blockorder="3">
    <foo>bar</foo>
</chronEntry>
<chronEntry type="experience" order="4" blockorder="3">
    <foo>bar</foo>
</chronEntry>
</chron>

取得したいのは、属性「タイプ」の使用可能なすべての値のリストです。- 教育 - コミュニティサービス - 経験

私はこのように試しました:

<xsl:for-each select="/foobar/chron/chronEntry">
            <xsl:sort select="@blockorder"/>
                <xsl:if test ="@blockorder != preceding-sibling::chronEntry[1]/@blockorder">
                    <fo:table-row>
                        <fo:table-cell>
                            <fo:block><xsl:value-of select="@type"/></fo:block>
                        </fo:table-cell>
                    </fo:table-row>
                </xsl:if>
            </xsl:for-each>

私が得るものは: - コミュニティサービス - 経験

「教育」が欠けています(最初のもの)

入手するにはどうすればよいですか?

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

グリーツ

デイブ

4

2 に答える 2

1

問題は、ソートされたノードリストを作成しているにもかかわらず、preceding-sibling::(または任意の軸) のみがドキュメント内のノード間の関係を表現するために使用できる (ノードリスト内ではない) ことです。

したがって、ソートされたノードリストではなく、現在のドキュメントのコンテキストノードのpreceding-sibling::chronEntry[1] chronEntry`。selects the first preceding sibling

解決策:

  1. XSLT 1.0xsl:for-eachでは、変数の結果をキャプチャします。これは悪名高い RTF タイプであるため、使用xxx:node-set()中の XSLT 1.0 プロセッサでサポートされている拡張関数を使用して、通常のツリーに変換する必要があります。次に、この通常のツリー内で、 を含む軸preceding-sibling::が必要な意味を持ちます。

  2. 推奨される解決策。Muenchian グループ化を使用します。

このような:

<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="kType" match="@type" use="."/>

 <xsl:template match=
  "chronEntry
    [generate-id(@type)
    =
     generate-id(key('kType', @type)[1])
    ]">
     <xsl:value-of select="concat(@type, ' ')"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

この変換が提供された XML ドキュメントに適用される場合:

<chron>
    <chronEntry type="education" order="1" blockorder="1">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="education" order="2" blockorder="1">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="education" order="3" blockorder="1">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="communityservice" order="1" blockorder="2">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="experience" order="1" blockorder="3">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="experience" order="2" blockorder="3">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="experience" order="3" blockorder="3">
        <foo>bar</foo>
    </chronEntry>
    <chronEntry type="experience" order="4" blockorder="3">
        <foo>bar</foo>
    </chronEntry>
</chron>

必要な正しい結果が生成されます。

education communityservice experience 
于 2012-04-10T12:34:41.640 に答える
0

xsl:sort は本当に必要ですか? またはグループ化に使用しましたか?その場合は、xsl:sort を削除して、xsl:if-test: を修正します。

        <xsl:for-each select="/foobar/chron/chronEntry">
            <xsl:if test ="not(@blockorder = preceding-sibling::chronEntry/@blockorder)">
                <fo:table-row>
                    <fo:table-cell>
                        <fo:block><xsl:value-of select="@type"/></fo:block>
                    </fo:table-cell>
                </fo:table-row>
            </xsl:if>
        </xsl:for-each>

xsl:sort が必要な場合は、これを使用できます。

        <xsl:variable name="types" select="/foobar/chron/chronEntry[not(preceding-sibling::*/@blockorder=@blockorder)]"/>
        <xsl:for-each select="$types">
            <xsl:sort select="@blockorder"/>
            <fo:table-row>
                <fo:table-cell>
                    <fo:block>
                        <xsl:value-of select="@type"/>
                    </fo:block>
                </fo:table-cell>
            </fo:table-row>
        </xsl:for-each>
于 2012-04-10T14:50:57.613 に答える