Разница в выводе между XSLT 1.0 и 2.0 заключается в том, что в 1.0 xsl:value-of
выводит строковое значение первого узла в выбранном наборе узлов, тогда как (IIRC) в 2.0, он выводит объединенныйзначения всех узлов в выбранном наборе узлов с пробелом в качестве разделителя по умолчанию.(Проверьте это, прежде чем верить мне.)
Итак, исходя из вашего вывода, похоже, что значение ключа для каждого элемента header
всегда равно 1. Я не уверен, что position()
дасткогда используется в атрибуте ключа use
(это зависит от контекста в том смысле, который я не искал), так что для меня это правдоподобно.
Вместо использования ключа с position()
Я бы попробовал что-то вроде:
<xsl:key name="header" match="header"
use="count(preceding-sibling::header) + 1" />
Это работает.Это может быть медленно, если у вас есть тысячи заголовков, но я полагаю, что вы никогда этого не сделаете.
В качестве альтернативы, вы можете решить не использовать ключи, а вместо этого сделать
<xsl:template match="data">
<xsl:variable name="posn" value="position()" />
<xsl:element name="{concat('bla-', $posn)}">
<xsl:value-of select="/root/headers/header[$posn]" />
</xsl:element>
</xsl:template>
Обычно используются ключидля повышения производительности, но в этом случае кажется неясным, что будет существенное преимущество по сравнению с использованием предиката [$posn]
.
Добавление:
Ответчтобы ваше «дополнение» выше было достаточно длинным, оно должно быть здесь, а не комментарий.В дополнение:
<xsl:template match="data">
<xsl:variable name="posn" select="position()" />
<xsl:element name="{key('header',1)[$posn]}" />
<xsl:element name="{key('header',1)[position()]}" />
Как указано в моем комментарии, контекст включает в себя как текущий узел , так и текущий список узлов .Для первого position()
при выборе переменной текущий список узлов состоит из всех элементов data
, которые являются дочерними элементами обрабатываемого элемента row
.Таким образом, position()
возвращает позицию текущего узла (элемент data
) в этом списке.Это значение сохраняется в переменной $posn
.
key('header',1)
дает список узлов всех элементов header
, по причинам, объясненным выше: значение ключа для каждого header
всегда равно 1. Итак key('header',1)[$posn]
дает n
th элемент заголовка, где n
- позиция текущего элемента данных среди его родных элементов.
Для второго вызова position()
: в предикате контекст определяетсяприменяя предикат индивидуально к каждому узлу в списке узлов, создаваемом выражением XPath до этой точки, с этим списком узлов в качестве списка текущих узлов .Таким образом, в квадратных скобках key('header',1)[...]
, список узлов контекста - это список узлов, возвращаемый key('header',1)
.Опять же, это список всех header
элементов.Таким образом, для каждого элемента header
, position()
здесь возвращает позицию этого заголовка среди его родных элементов.
Теперь мы немного глубже ... Предикаты по своей природе булевы, но когда выражение e
в предикате является числовым, он рассматривается как сокращение для position() = e
.Таким образом, ваше выражение имени второго элемента эквивалентно
<xsl:element name="{key('header',1)[position() = position()]}" />
и position() = position()
всегда верно для любого заданного контекста, поэтому приведенное выше эквивалентно
<xsl:element name="{key('header',1)}" />
, который является спискомвсе заголовки.