Синтаксис XSLT и Xpath > как ссылаться на элемент во "внешней" области

StackOverflow https://stackoverflow.com/questions/1843693

  •  12-09-2019
  •  | 
  •  

Вопрос

У меня следующее работает на 100% корректно.Однако, чтобы удовлетворить мое любопытство...есть ли способ добиться того же без объявления переменной currentId?Есть ли какой-нибудь способ ссылаться на него из условия Xpath "test"?

Запрос xpath в условии должен ссылаться на 2 атрибута @id, чтобы проверить, совпадают ли они.

  • "текущий" @id
  • каждый "предок" @id

Вот код:

<xsl:variable name="currentID" select="@id" />
<xsl:attribute name="class">
<xsl:if test="count($currentPage/ancestor::node [@id = $currentID])&gt;0">descendant-selected </xsl:if>
</xsl:attribute>
Это было полезно?

Решение

Поскольку вы выбираете $currentID из контекстного узла:

<xsl:variable name="currentID" select="@id" />

вы можете использовать current() функция, которая всегда ссылается на контекстный узел XSLT:

<xsl:attribute name="class">
  <xsl:if test="count($currentPage/ancestor::node[@id = current()/@id) &gt; 0]">
    <xsl:text>descendant-selected </xsl:text>
  </xsl:if>
</xsl:attribute>

Таким образом, вам не нужна переменная.

Несколько других заметок:

  • Я рекомендую использовать <xsl:text> как показано выше.Это дает вам больше свободы в форматировании вашего кода и позволяет избежать чрезмерно длинных строк.
  • Вам не нужно делать count() > 0, достаточно простого выбора узлов.Если таковых не существует, возвращается пустой набор узлов.Он всегда принимает значение false, в то время как непустые наборы узлов всегда принимают значение true.

Если вы ссылаетесь на узлы с помощью @id регулярно в вашей таблице стилей XSL появляется <xsl:key> стало бы полезным:

<xsl:key name="kNodeById" match="node" use="@id" />

<!-- ... -->

<xsl:attribute name="class">
  <xsl:if test="key('kNodeById', @id)">
    <xsl:text>descendant-selected </xsl:text>
  </xsl:if>
</xsl:attribute>

Вышесказанное не нужно current() поскольку вне предиката XPath контекст остается неизменным.Кроме того, я не count() узлы, поскольку это избыточно (как объяснено).

Другие советы

Используйте current() для ссылки на текущий узел, обрабатываемый шаблоном:

<xsl:if test="count($currentPage/ancestor::node [@id = current()/@id])&gt;0">

Тим заставил меня задуматься....Я думаю, что я перестарался усложнять ситуацию, и я попробовал следующее, которое работает.

<xsl:if test="@id = $currentPage/ancestor::node/@id">descendant-selected </xsl:if>

XSLT, кажется, доволен сравнением атрибута с набором атрибутов и оценкой true, если какой-либо из них совпадает?если у кого-нибудь есть лучшее объяснение, почему это работает, или что-то лучшее (более краткое), то опустите это.

Как уже стало ясно, ссылка на "внешнюю область" не была проблемой, поскольку вы могли выполнить прямое сравнение с помощью оператора "=".Однако есть некоторые случаи, когда вам действительно нужен current() и многое другое, кроме того, когда даже current() не сокращает его (потому что вам нужно "объединить" более чем два контекста).В таких случаях выражения XPath 2.0 "for" незаменимы.

Вы могли бы просто сделать:

<xsl:if test="count($currentPage[ancestor::node/@id = @id])&gt;0">descendant-selected </xsl:if>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top