XSLT - Как сослаться на текущее значение узла, используя xsl: select?

Я пытаюсь создать переменную, которую я могу использовать в следующем шаблоне:

<xsl:variable name="fc">
    <xsl:choose>
        <xsl:when test="self::node()='element1'">gray</xsl:when>
        <xsl:otherwise>red</xsl:otherwise>
    </xsl:choose>
</xsl:variable>

К сожалению, это не работает.

<xsl:template match="element1">
    <h1><font color="{$fc}"><xsl:value-of select="self::node()"/></font></h1>
</xsl:template>

Что я делаю неправильно?

Вот обширный код:

XML:

<root 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.test.com scheme.xsd" xmlns="http://www.test.com" xmlns:tst="http://www.test.com">
 <elementA>
    <elementB tst:name="name">
        <elementC tst:name="name">
            <element1> Test1 </element1>
            <element2> Test2 </element2>
         </elementC >
    </elementB> 
  </elementA>    
</root>

Все элементы квалифицированы и являются частью пространства имен " http://www.test.com/".

XSLT:

<xsl:template match="/">
<html>
<body><xsl:apply-templates select="tst:root/tst:elementA/tst:elementB/tst:elementC/tst:element1"/>
</body>
</html>

</xsl:template>
<xsl:variable name="var_fc">
<xsl:choose>
    <xsl:when test="local-name(.)='tst:element1'">gray</xsl:when>
    <xsl:otherwise>red</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:template match="tst:element1">
<h2><font color="{$var_fc}"><xsl:value-of select="self::node()"/></font></h2>
</xsl:template>

В результате element1 должен стать серым, но он всегда станет красным.

5 ответов

Решение

Вы не можете использовать переменную для этого, так как содержимое xsl:variable оценивается только один раз во время определения, тогда как вы хотите оценивать некоторую логику каждый раз, когда на переменную ссылаются, в текущем контексте в точке ссылки.

Вместо этого вам нужен шаблон, либо именованный:

<xsl:template name="fc">
  <xsl:choose>
    <xsl:when test="local-name()='element1'">gray</xsl:when>
    <xsl:otherwise>red</xsl:otherwise>
  </xsl:choose>
</xsl:template>

или (лучше) пара подходящих шаблонов с режимом, чтобы позволить шаблонному сопоставителю выполнить работу:

<!-- match any node whose local name is "element1" -->
<xsl:template mode="fc" match="node()[local-name() = 'element1']">gray</xsl:template>

<!-- match any other node -->
<xsl:template mode="fc" match="node()">red</xsl:template>

Когда вы хотите использовать эту логику:

<h1>
  <font>
    <xsl:attribute name="color">
      <xsl:apply-templates select="." mode="fc" />
    </xsl:attribute>

Видя, как у вас есть tst Префикс отображается в вашей таблице стилей, вы можете проверить имя непосредственно вместо использования local-name() сказуемое:

<xsl:template mode="fc" match="tst:element1">gray</xsl:template>
<xsl:template mode="fc" match="node()">red</xsl:template>

Переменные XSLT разработаны так, чтобы их нельзя было изменять. На самом деле их можно назвать постоянными. Если ваша переменная fc создана глобальной, она будет использовать корневой элемент для выбора. Вы должны использовать выбор в фактическом шаблоне, который будет проверен против текущего элемента. Если вы хотите, чтобы "красный" и "серый" определялись только один раз, создайте две переменные только с этим текстовым содержимым и используйте их вместо простого текста в выборе.

Я думаю вместо test="self::node()='element1'" ты хочешь test="self::element1" или же test="local-name(.) = 'element1'",

Может быть, это опечатка

<xsl:when test=self::node()='element1'">gray</xsl:when>

должно быть:

<xsl:when test="self::node()='element1'">gray</xsl:when>

пропущенная цитата

Пара других ошибок в вашем коде:

(1) self::node() = 'element1'

проверяет, является ли содержимое элемента "element1", а не его имя "element1"

(2) local-name(.)='tst:element1'

никогда не будет истинным, потому что локальное имя узла никогда не содержит двоеточия.

Опытные пользователи часто пишут этот код, используя правила шаблона:

<xsl:template mode="var_fc" match="tst:element1">gray</xsl:template>
<xsl:template mode="var_fc" match="*">red</xsl:template>

а потом

<xsl:apply-templates select="." mode="var_fc"/>
Другие вопросы по тегам