Ссылка на позицию текущего узла в выражении xpath

(Примечание: этот пост был отредактирован, чтобы показать конкретный вариант использования. См. внизу.)

Я хочу использовать значение position() узла current внутри выражения xpath (в котором изменяется контекст). К сожалению, я не вижу простого способа сделать это, потому что current()/position() всегда равны 1.

[Я предполагаю, что это потому, что current()/position() говорит: «Какова позиция узла current() в контексте... набора из одного узла, содержащего только current().]

Чтобы быть конкретным, предположим, что у меня есть последовательность узлов $seq, и я хочу вернуть *n*й узел в последовательности ($seq[n]), где n равно текущему значению position() (то есть значение position() до оцениваемого оператора).

Ясно, что $seq[position()] не будет работать, потому что это расширяется до seq[position() = position()], возвращая всю последовательность.

$seq[position(current())] — это бред.

Единственное, что я мог найти, что, возможно, работает, это

for $pos in position() return $seq[$pos]

Я предполагаю, что есть более простой способ.

Изменить Меня попросили привести более конкретный пример того, что я пытаюсь сделать. На самом деле я нашел ответ первого человека достаточным для моих нужд, хотя и не намного проще, чем то, что я придумал сам (опция «for $pos in position() return $correctOrder[$pos]»).

Вот реальная ситуация: у меня есть набор «сеансовых» узлов, каждый из которых имеет атрибут @startTime. Я хочу найти, какие из них не соответствуют этому атрибуту @startTime или, по крайней мере, находятся не в том месте, где они были бы, если бы узлы входного документа были правильно отсортированы по @startTime.

Это всего лишь один из многих тестов, которые выполняются на каждом из узлов сеанса.

Что я хотел сделать, так это создать последовательность, в которой узлы были в правильном порядке, и сравнить n-й элемент в упорядоченной по документам последовательности с n-м элементом в правильно упорядоченной последовательности.

Что-то вроде этого:

<xsl:template match="/">
<xsl:variable name="correctOrder" as="node()*">
<xsl:for-each select="session">
<xsl:sort select="@xs:dateTime(@startTime)"/>
<xsl:sequence select="."/>
</xsl:for-each>
</xsl:variable>

<xsl:for-each select="session">

‹---- Множество различных тестов ---->

<xsl:if test="current()/@startTime eq 
$correctOrder[<-here I want to put the value "position()" had prior to this <xsl:if> statement->]/@startTime"
<error description="Node out of order."/>
</xsl:if>

‹--- Множество других тестов ----->

</xsl:for-each>

person David R    schedule 28.01.2012    source источник
comment
Дэвид Р: position() сам по себе не определен. position() против чего? Пожалуйста, отредактируйте вопрос и сделайте его менее двусмысленным и более четким. Конкретный пример был бы отличным.   -  person Dimitre Novatchev    schedule 28.01.2012
comment
Димитре, я указал конкретный вариант использования, но я думаю, что вопрос задавался, как ссылаться на значение, которое position() имело до вызова данной инструкции? захватывает то, что я искал. Вот почему у нас есть current() (в отличие от .), потому что мы хотим ссылаться на текущий узел (а не на узел контекста) в некотором выражении xpath. Я просто спрашиваю об эквивалентной идее для различных других переменных контекста, которые изменяются посреди выражения xpath.   -  person David R    schedule 29.01.2012
comment
Дэвид Р.: Да, теперь ясно. Что касается сохранения или синхронизации разных позиций, я показал, как это сделать в своем ответе.   -  person Dimitre Novatchev    schedule 29.01.2012


Ответы (2)


Ну, поскольку вы пометили свой вопрос как XSLT 2.0, я бы использовал переменную, например.

<xsl:variable name="pos" as="xs:integer" select="position()"/>

а затем используйте эту переменную, например.

<xsl:sequence select="$seq[$pos]"/>
person Martin Honnen    schedule 28.01.2012
comment
по какой-то причине я думал, что переменные можно объявлять только вверху шаблонов, документов и функций. Я думаю, это относится только к параметрам. - person David R; 28.01.2012
comment
Вопрос: есть ли причина, по которой ‹xsl:value-of select=$seq[$pos]/› не работает? - person David R; 28.01.2012
comment
@DavidR: Причина, по которой это не сработает, заключается в том, что вы не сказали нам, что вы понимаете под позицией. Принимая это во внимание, ответ Мартина, вероятно, неверен, потому что он не телепат, чтобы копаться в вашем мозгу и получать то, что вы действительно хотите. - person Dimitre Novatchev; 28.01.2012
comment
Дэвид, мое главное предложение — использовать xsl:variable, как показано, а затем использовать эту переменную в любом выражении, которое вам нужно или нужно. xsl:sequence просто дает пример кода XSLT, который подходит для большинства целей XSLT 2.0, если xsl:value-of дает вам то, что вы хотите, вы, конечно, можете использовать его вместо xsl:sequence. - person Martin Honnen; 28.01.2012

Примечание. Я прошу прощения за то, что из-за ошибки в форматировании кода SO этот код не имеет отступа.

Вот пример, иллюстрирующий общий шаблон с использованием одной и той же позиции:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/> 

 <xsl:variable name="vSeq1" select="/*/names/*/text()"/>
 <xsl:variable name="vSeq2" select="/*/values/*/text()"/>

 <xsl:template match="/">
  <xsl:sequence select=
   "for $i in 1 to count($vSeq1)
     return
        ($vSeq1[$i], '=', $vSeq2[$i], '&#xA;')

   "/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к следующему XML-документу:

<t>
 <names> 
  <name>N1</name>
  <name>N2</name>
  <name>N3</name>
  <name>N4</name>
  <name>N5</name>
 </names>

 <values>
  <value>V1</value>
  <value>V2</value>
  <value>V3</value>
  <value>V4</value>
  <value>V5</value>
 </values>
</t>

получен желаемый правильный результат:

N1=V1
N2=V2
N3=V3
N4=V4
N5=V5
person Dimitre Novatchev    schedule 29.01.2012
comment
Спасибо, Димитр. Я только недавно начал использовать мощь последовательностей xslt2. Я думаю, что вчера я прошел своего рода веху в моем понимании xslt2 ... многое еще предстоит сделать. - person David R; 30.01.2012