3

私は、XSLT キーに関する単純な問題に悩まされています。

関連がある場合は、XSLT 1.0 パーサーを使用する必要があります。

サンプル XML:

<updates>
  <update>
    <id>first</id>
    <pkglist>
      <collection arch='i686'>
        <package name='bin' version='1.0'/>
      </collection>
      <collection arch='x86_64'>
        <package name='bin' version='1.0'/>
      </collection>
    </pkglist>
  </update>
  <update>
    <id>second</id>
    <pkglist>
      <collection arch='i686'>
        <package name='bin' version='1.1'/>
        <package name='conf' version='1.1'/>
      </collection>
      <collection arch='x86_64'>
        <package name='bin' version='1.2'/>
        <package name='conf' version='1.1'/>
      </collection>
    </pkglist>
  </update>
  <update>
    <id>third</id>
    <pkglist>
      <collection arch='i686'>
        <package name='bin' version='1.3'/>
        <package name='conf' version='1.1'/>
        <package name='src' version='1.3'/>
      </collection>
      <collection arch='x86_64'>
        <package name='bin' version='1.3'/>
        <package name='conf' version='1.2'/>
        <package name='src' version='1.3'/>
      </collection>
    </pkglist>
  </update>
</updates>

この XPATH は、私が探しているものを選択します

/updates//update[pkglist/collection/package/@name = 'bin']/id/text()

「名前」の属性を持つパッケージを持つドキュメント全体ですべての「id」値を探しています。しかし、現実の世界では、手作業でリストするよりもはるかに多くのパッケージがあります。

だから私は鍵が行く方法になるだろうと考えました

<xsl:key name="idByPackage" match="/updates//update/pkglist/collection/package/@name" use="../../../../id" />

しかし、それは私に有用なものを何も返してくれません

<xsl:key name="idByPackage" match="/updates//update/pkglist/collection/package/@name" use="../../../../id" />

<xsl:template match="/">
    <xsl:apply-templates select="updates/update" />
</xsl:template>
<xsl:template match="update">
    Updates:
    <xsl:value-of select="id" />
    Related updates
    <xsl:apply-templates select="pkglist" />
</xsl:template>
<xsl:template match="pkglist">
    <xsl:for-each select="key('idByPackage', collection/package/@name)">
        <xsl:value-of select="." />
        <xsl:value-of select="collection/package/@name" />
    </xsl:for-each>
</xsl:template>

キーをこれに変更したときのように、私は正しい領域にいることを知っています:

<xsl:key name="idByPackage" match="/updates//update/pkglist/collection/package/@name" use="../../../../pkglist/collection/package/@name" />

同じ xsl テンプレートが私のパッケージ名をパックします。

「私には有効に見えますが、機能しません」キーを使用してテンプレートを実行すると、次のようになります。

Updates:
first
Related updates
Updates:
second
Related updates
Updates: third
Related updates

次のようなものを期待するとき

Updates:
first
Related updates
second
third
Updates:
second
Related updates
first
third
Updates: third
Related updates 
first
second

私は何を間違っていますか?

4

1 に答える 1

4

必要なキーは次のとおりです。

<xsl:key name="idByPackage" 
         match="update/id" use="../pkglist/collection/package/@name" />

サンプル入力に対してこの XSLT を実行すると、次のようになります。

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

  <xsl:key name="idByPackage"
           match="update/id" use="../pkglist/collection/package/@name" />
  <xsl:variable name="nl" select="'&#xA;'" />

  <xsl:template match="/">
    <xsl:apply-templates select="updates/update" />
  </xsl:template>

  <xsl:template match="update">
    <xsl:value-of select="concat('Updates:', $nl, 
                                 id, $nl, 
                                 'Related updates:', $nl)" />

    <xsl:variable name="name" select="pkglist/collection/package/@name" />
    <xsl:apply-templates select="key('idByPackage', $name)[. != current()/id]" />
  </xsl:template>

  <xsl:template match="id">
    <xsl:value-of select="concat(., $nl)" />
  </xsl:template>

</xsl:stylesheet>

結果は次のとおりです。

Updates:
first
Related updates:
second
third
Updates:
second
Related updates:
first
third
Updates:
third
Related updates:
first
second
于 2013-04-19T18:41:40.100 に答える