ノードの数をカウントしたいXMLファイルを処理しているので、新しいノードを作成するときにIDとして使用できます。
現時点では、「counter」というグローバル変数があります。テンプレート内でアクセスできますが、テンプレート内で操作する方法が見つかりませんでした。
XSLTファイルの要約版は次のとおりです。
<xsl:variable name="counter" select="1" as="xs:integer"/>
<xsl:template match="/">
<xsl:for-each select="section">
<xsl:call-template name="section"></xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="section">
<!-- Increment 'counter' here -->
<span class="title" id="title-{$counter}"><xsl:value-of select="title"/></span>
</xsl:template>
ここから行く方法はありますか?
他の人は、変数がどのように不変であるかをすでに説明しています-XSLTには代入ステートメントがないこと(一般に純粋に機能的なプログラミング言語の場合と同様)。
これまでに提案されたソリューションの代替手段があります。パラメーターの受け渡しを回避します(XSLTでは冗長で見苦しいです。私も認めます)。
XPathでは、現在の要素の前にある<section>
要素の数を単純にカウントできます。
<xsl:template name="section">
<span class="title" id="title-{1 + count(preceding-sibling::section)}">
<xsl:value-of select="title"/>
</span>
</xsl:template>
(注:空白のみのテキストノードはスタイルシートから自動的に削除されるため、空白コードの書式設定は結果に表示されません。そのため、同じ行に命令を配置する必要はありません。)
(position()
を使用するのとは対照的に)このアプローチの1つの大きな利点は、現在のノードリストではなく、現在のノードのみに依存することです。何らかの方法で処理を変更した場合(たとえば、<xsl:for-each>
がセクションだけでなく他の要素も処理した場合)、position()
の値はドキュメントの<section>
要素の位置に必ずしも対応しなくなります。一方、上記のようにcount()
を使用すると、常に各<section>
要素の位置に対応します。このアプローチは、コードの他の部分との結合を減らします。これは一般的に非常に良いことです。
Count()の代わりに<xsl:number>
命令を使用することもできます。デフォルトの動作では、同じ名前のすべての要素に同じレベルの番号が付けられます。
<xsl:template name="section">
<xsl:variable name="count">
<xsl:number/>
</xsl:variable>
<span class="title" id="title-{$count}">
<xsl:value-of select="title"/>
</span>
</xsl:template>
これは冗長性のトレードオフです(属性値テンプレートの中括弧を引き続き使用する場合は追加の変数宣言が必要です)が、XPath式も大幅に簡素化されるため、ほんの少しだけです。
まだ改善の余地があります。現在のノードリストへの依存関係を削除しましたが、まだ現在のノードに依存しています。それ自体は悪いことではありませんが、現在のノードが何であるかをテンプレートで確認してもすぐにはわかりません。わかっているのは、テンプレートの名前が「section
」であることだけです。何が処理されているかを確実に知るには、コードの別の場所を調べる必要があります。しかし、そうである必要はありません。
(例のように)<xsl:for-each>
と<xsl:call-template>
を一緒に使用することになったと感じた場合は、戻って、代わりに<xsl:apply-templates>
を使用する方法を見つけてください。
<xsl:template match="/doc">
<xsl:apply-templates select="section"/>
</xsl:template>
<xsl:template match="section">
<xsl:variable name="count">
<xsl:number/>
</xsl:variable>
<span class="title" id="title-{$count}">
<xsl:value-of select="title"/>
</span>
</xsl:template>
このアプローチは冗長性が低い(<xsl:apply-templates/>
が<xsl:for-each>
と<xsl:call-template/>
の両方を置き換える)だけでなく、現在のノードが何であるかがすぐに明らかになります。 match
属性を調べるだけで、<section>
要素を処理しており、<section>
要素がカウントしていることがすぐにわかります。
テンプレートルール(つまり、match
属性を持つ<xsl:template>
要素)の仕組みの簡潔な説明については、 "XSLTの仕組み" を参照してください。
XSLT変数は変更できません。テンプレートからテンプレートに値を渡す必要があります。
XSLT 2.0を使用している場合、パラメーターを設定し、トンネリングを使用して変数を適切なテンプレートに伝播できます。
テンプレートは次のようになります。
<xsl:template match="a">
<xsl:param name="count" select="0">
<xsl:apply-templates>
<xsl:with-param select="$count+1"/>
</xsl:apply-templates>
</xsl:template>
IDを作成する場合は、generate-id()の使用も参照してください。
XSLTの変数は不変であるため、それを念頭に置いて問題にアプローチする必要があります。 position()
を直接使用できます:
<xsl:template match="/">
<xsl:for-each select="section">
<xsl:call-template name="section"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="section">
<span class="title" id="title-{position()}"><xsl:value-of select="title"/></span>
</xsl:template>
または、よりテンプレート指向の方法で:
<xsl:template match="/">
<xsl:apply-templates select="section"/>
</xsl:template>
<xsl:template match="section">
<span class="title" id="title-{position()}"><xsl:value-of select="title"/></span>
</xsl:template>
変数はローカルにスコープされ、xsltでのみ読み取ります。
XSLTプロセッサーによっては、スクリプト化された関数をXLSTに導入できる場合があります。たとえば、Microsoft XMLライブラリはjavascriptの組み込みをサポートしています。例については、 http://msdn.Microsoft.com/en-us/library/aa970889(VS.85).aspx を参照してください。パブリッククライアントブラウザーでXSLTを展開/実行することを計画している場合、この戦術は明らかに機能しません。特定のXSLTプロセッサで実行する必要があります。
Position()関数を使用して、必要な処理を実行できます。これは次のようになります。
<xsl:template match="/">
<xsl:for-each select="section">
<xsl:call-template name="section">
<xsl:with-param name="counter" select="{position()}"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="section">
<xsl:param name="counter"/>
<span class="title" id="title-{$counter}">
<xsl:value-of select="title"/>
</span>
</xsl:template>
<xsl:variable name="RowNum" select="count(./preceding-sibling::*)" />
および$ RowNumを増分値として使用します。
例:<xsl:template name="ME-homeTiles" match="Row[@Style='ME-homeTiles']" mode="itemstyle"> <xsl:variable name="RowNum" select="count(./preceding-sibling::*)" /> ...<a href="{$SafeLinkUrl}" class="tile{$RowNum}"><img ....></a>
これにより、tile1、tile2、tile3などの値を持つリンクのクラスが作成されます。
自分で試したことはありませんが、テンプレートにパラメータを渡してみてください。最初のテンプレートでは、for-eachステートメント内でパラメーターをcount()(またはcurrent()多分?)に設定し、その値を「セクション」テンプレートに渡します。
テンプレートにパラメーターを渡す の詳細