for-eachで選択した各ノードにテンプレートを適用するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/1620527

  •  06-07-2019
  •  | 
  •  

質問

ここで何かが欠けていることは知っています。以下のXSLT変換では、実際の結果は目的の結果と一致しません。

for-each内で、選択した各match="track"要素にtrackテンプレートを適用します。 XSLTを正しく理解していれば、現在の設定では、選択した各<=>要素の子ノードのみがテンプレートと照合され、<=>要素自体は照合されません。

必要に応じて<=>要素をテンプレートを通過させるにはどうすればよいですか?アプローチ全体を再考する必要がありますか?

注:変換はPHPを使用して実行されます。簡潔にするため、XML宣言は省略されています。

XMLドキュメント:

<album>
    <title>Grave Dancers Union</title>
    <track id="shove">Somebody To Shove</track>
    <track id="gold">Black Gold</track>
    <track id="train">Runaway Train</track>
    <producer>Michael Beinhorn</producer>
</album>

XSLスタイルシート:

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/album">
        <ol>
            <xsl:for-each select="track">
                <li><xsl:apply-templates/></li>
            </xsl:for-each>
        </ol>
    </xsl:template>

    <xsl:template match="track">
        <a href="{@id}"><xsl:apply-templates/></a>
    </xsl:template>
</xsl:stylesheet>

結果:

<ol>
    <li>Somebody To Shove</li>
    <li>Black Gold</li>
    <li>Runaway Train</li>
</ol>

望ましい結果:

<ol>
    <li><a href="shove">Somebody To Shove</a></li>
    <li><a href="gold">Black Gold</a></li>
    <li><a href="train">Runaway Train</a></li>
</ol>
役に立ちましたか?

解決

xndl:for-eachループを廃止するために、おそらくXSLTを再構築する必要があるという「ndim」に同意します。

また、xsl:apply-templatesを修正して、xsl:for-each内の現在のトラックノードを選択することもできます

<xsl:for-each select="track">
   <li>
      <xsl:apply-templates select="." />
   </li>
</xsl:for-each>

xsl:for-eachを保持することで、少なくとも、必要に応じて別の順序でトラックを並べ替えることができます。

他のヒント

少し再構築します(ソートが必要ない場合は、for-eachアプローチが可能になります):

<xsl:template match="/album">
  <ol>
    <xsl:apply-templates select="track"/>
  </ol>
</xsl:template>

<xsl:template match="track">
  <li><a href="{@id}"><xsl:apply-templates/></a></li>
<xsl:template>

これはより短く、要点、IMHOに見えます。

あなたの推測

    <xsl:for-each select="track">
       <li><xsl:apply-templates/></li>
    </xsl:for-each>

は、match="track"を使用してすべてのトラック要素をウォークスルーし、デフォルトのルールをその子孫に適用します。そのため、name="track"のコンテンツは<xsl:call-template/>テンプレートと同じコンテキストノードを持つため、Tim Cテンプレートは一致しません。

本当に<xsl:apply-templates select="."/>をそのように使用する場合は、アプローチで次の2つのいずれかを変更する必要があります。

  1. <=>テンプレートに<=>属性を追加してから、<=>内から<=>を使用します(私の考えであり、<=>よりも悪い)
  2. <=>を使用して<=>のソリューションを使用します。これには、命名を避け、トラックをソートする可能性を維持するという利点があります。

apply-templatesとテンプレートモードを使用する方がよりクリーンなソリューションだと思います:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="/">
    <body>
      <xsl:apply-templates select="album" mode="ol" />
    </body>
  </xsl:template>

  <xsl:template match="album" mode="ol">
    <ol>
      <xsl:apply-templates select="track" mode="li" />
    </ol>
  </xsl:template>

  <xsl:template match="track" mode="li">
    <li>
      <xsl:apply-templates select="." />
    </li>
  </xsl:template>

  <xsl:template match="track">
    <a href="{@id}">
      <xsl:value-of select="." />
    </a>
  </xsl:template>


</xsl:stylesheet>

結果:

<body>
  <ol>
    <li>
      <a href="shove">Somebody To Shove</a>
    </li>
    <li>
      <a href="gold">Black Gold</a>
    </li>
    <li>
      <a href="train">Runaway Train</a>
    </li>
  </ol>
</body>

for-eachステートメントは、コンテキストノードをアルバムからトラックに変更します。 デフォルトでは、apply-templates呼び出しは、テンプレートをコンテキストノードの子ノードに適用します。これは、場合によってはtrack要素の子ノードです。したがって、「トラック」に一致するテンプレートはヒットしません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top