for-eachで選択した各ノードにテンプレートを適用するにはどうすればよいですか?
-
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つのいずれかを変更する必要があります。
- <=>テンプレートに<=>属性を追加してから、<=>内から<=>を使用します(私の考えであり、<=>よりも悪い)
- <=>を使用して<=>のソリューションを使用します。これには、命名を避け、トラックをソートする可能性を維持するという利点があります。
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要素の子ノードです。したがって、「トラック」に一致するテンプレートはヒットしません。