Ответ 1
Вы можете использовать
<xsl:value-of select="count(preceding-sibling::record)" />
или даже, вообще говоря,
<xsl:value-of select="count(preceding-sibling::*[name() = name(current())])" />
Конечно, этот подход не будет работать, если вы обрабатываете список узлов, которые не являются равномерными, то есть:
<xsl:apply-templates select="here/foo|/somewhere/else/bar" />
Информация о местоположении теряется в таком случае, если вы не сохранили ее в переменной и не передали ее вызываемому шаблону:
<xsl:variable name="pos" select="position()" />
<xsl:for-each select="$record">
<xsl:call-template name="SomeTemplate">
<xsl:with-param name="pos" select="$pos" />
</xsl:call-template>
</xsl:for-each>
но, очевидно, это означало бы некоторую перекодировку кода, которую я понимаю, чего вы хотите избежать.
Финальный намек: position()
не указывает вам позицию node внутри своего родителя. Он сообщает вам позицию текущего node относительно списка узлов, которые вы обрабатываете прямо сейчас.
Если вы только обрабатываете (т.е. "применяете шаблоны к" или "перебираете" ) узлы внутри одного родителя, это происходит одинаково. Если вы этого не сделаете, это не так.
Окончательный намек № 2: Этот
<xsl:for-each select="/path/to/record">
<xsl:variable name="record" select="."/>
<xsl:for-each select="$record">
<xsl:call-template name="SomeTemplate"/>
</xsl:for-each>
</xsl:for-each>
эквивалентно этому:
<xsl:for-each select="/path/to/record">
<xsl:call-template name="SomeTemplate"/>
</xsl:for-each>
но последний работает без разрушения значения position()
. Вызов шаблона не меняет контекста, поэтому .
будет ссылаться на правильный node с вызываемым шаблоном.