Текущий node против контекста node в XSLT/XPath?

В XSLT, в чем разница между "текущим node" и "контекстом node"? Вы можете найти оба используемых здесь термина: http://www.w3.org/TR/xslt.

Когда вы будете использовать тот или иной? Как вы относитесь к каждому?

Ответ 1

Текущий node работает независимо от того, какой шаблон работает. Обычно это также является контекстом node, но контекст node имеет особое значение внутри вложенного выражения XPath (часть в квадратных скобках). Там он ссылается на то, что node в настоящее время тестируется на соответствие. Следовательно, контекст node изменяется в выражении XPath, но не в текущем node.

Контекст node может быть сокращен точкой (.) или иногда полностью исключен. Это, вероятно, немного запутанно, потому что вне вложенного выражения точка обозначает текущий node. (В этом случае текущий node является контекстом node, поэтому можно сказать, что он является текущим node только ближе, и его более правильно называют контекстом node. Но даже вызовы spec это текущий node здесь.)

Поскольку точка дает вам контекст node, во вложенном выражении XPath пользователю нужен способ вернуться к текущему node, который обрабатывается текущим шаблоном. Вы можете сделать это с помощью функции current().

Отличие этих двух полезно в некоторых случаях. Например, предположим, что у вас есть такой XML:

<a>
    <b>
        <c>foo<footnote fn="1"/></c>
        <d>bar</d>
    </b>
    <b>
        <c>baz</c>
        <d>aak<footnote fn="2"/></d>
    </b>
    <b>
        <c>eep</c>
        <d>blech<footnote fn="2"/></d>
    </b>
    <footnote-message fn="1">Batteries not included.</footnote>
    <footnote-message fn="2">Some assembly required.</footnote>
</a>

Теперь предположим, что вы хотите преобразовать его в LaTeX следующим образом:

foo\footnote{Batteries not included.}
bar

baz
aak\footnote{Some assembly required.}

eep
blech\footnotemark[2]

Трюк - это сказать, была ли уже использована сноска или нет. Если вы впервые встретили сноску, вы хотите написать команду \footnote; в противном случае вы хотите написать команду \footnotemark. Вы можете использовать XSL-код следующим образом:

<xsl:choose>
    <xsl:when test="count(preceding::*[./@fn = current()/@fn]) = 0">\footnote{...}</xsl:when>
    <xsl:otherwise>\footnotemark[...]</xsl:otherwise>
</xsl:choose>

Здесь мы сравниваем атрибут context- node fn (из результатов preceding::* node -set) с атрибутом current- node fn. (Вы действительно не должны говорить ./@fn, вы можете просто сказать @fn.)

Итак, контекст node оставляет вас внутри предиката XPath; текущий node выходит за пределы предиката, обратно к node, обрабатываемому текущим шаблоном.