Почему мои переменные XSLT не заменяют свои значения?

Я пытаюсь использовать переменные XSLT и не добился большого успеха, надеюсь, я просто делаю что-то глупое.

У меня есть следующий фрагмент кода:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xalan="http://xml.apache.org/xslt"
  version="1.0">

    <xsl:template match="/">
      <xsl:variable name="config" select="query/@config"></xsl:variable>

поэтому я ожидаю, что для переменной 'config' будет установлено значение атрибута 'config' моего элемента верхнего уровня 'query'.

Затем я пытаюсь использовать переменную позже в своей таблице стилей, например:

<a href="localhost/test?go">
    {$config}
</a>

но вывод, который я вижу в своем выходном HTML-документе:

<a href="localhost/test?go">
    {$config}
</a>

поэтому значение не было заменено, как я ожидал.

Я думаю, что это самый простой случай, который может быть, поэтому я делаю глупость! Пожалуйста, помогите, спасибо!


ОБНОВЛЕНИЕ спасибо всем, кто ответил, я неправильно понял разные контексты того, работал ли я в атрибуте или снаружи. Отлично решил мою проблему!

Если бы я мог, я бы принял два ответа: тот, который у меня есть, и ответ @Aaron Digulla, который объясняет атрибуты.


person brabster    schedule 11.03.2009    source источник


Ответы (6)


В вашей таблице стилей вы должны использовать:

<xsl:value-of select="$config"/>

вместо:

{$config}
person Laurent    schedule 11.03.2009

Здесь есть два вопроса, которые кажутся одинаковыми, но немного различаются: 1) Как ссылаться на переменную по имени? 2) Где я могу ссылаться на переменную по имени?

Во-первых, переменные всегда упоминаются с использованием синтаксиса $varname. Во-вторых, это можно сделать везде, где разрешены выражения. Это вторая часть, которая, кажется, сбивает с толку. Начнем с того, что значение элемента или атрибута по умолчанию будет выводиться буквально, поэтому в следующем примере на самом деле не ссылаются ни на какие переменные:

<element attr="$test">$test or {$test}</element>

Вывод будет буквально соответствовать тому, что было напечатано.

Чтобы вывести значение переменной, нам нужно сослаться на нее там, где разрешено выражение. В содержимом элемента мы используем xsl:value-of; в атрибутах, которые рассматриваются как Шаблон значения атрибута (например, атрибуты литеральный элемент результата), выражения разделяются фигурными скобками {}. Предположим следующее объявление:

<xsl:variable name="test" select="'value'"/>

...тогда следующее:

<element attr="{$test}"><xsl:value-of select="$test"/></element>

...результат:

<element attr="value">value</element>

Несколько напутственных замечаний по АВЦ и value-of:

  • В обоих случаях переменная упоминалась как $test. Фигурные скобки в AVT не являются частью ссылки на переменную; они являются разделителями выражений.
  • В любом случае выражение не обязательно должно содержать ссылку на переменную; любое выражение XPath было бы разрешено.
  • Не все атрибуты в XSLT-документе рассматриваются как шаблоны значений атрибутов. Например, обратите внимание, что атрибут select элемента xsl:value уже принимает выражение в качестве содержания.
  • Вопрос. Почему нельзя использовать value-of в атрибуте вот так?

    <element attr="<xsl:value-of select="$test"/>"/>
    

    Ответ: потому что документы XSLT должны содержать правильно сформированный XML (а это не так).

  • Вопрос. Почему нельзя использовать {$varname} в содержимом элемента?

    Гибкий ответ: потому что создатели XSLT не планировали его таким образом.

person Wayne    schedule 14.12.2011
comment
Взгляните на ответ, который я добавил: последний вопрос/ответ в вашем ответе. Не уверен, видели ли вы это еще (поскольку ваш ответ такой старый). - person Daniel Haley; 13.05.2014
comment
Спасибо за столь четкое объяснение различных синтаксисов для ссылок на переменные в разных местах. Я нашел это, когда искал объяснение синтаксиса {}. Спасибо! - person levininja; 22.05.2014

{$config} работает только в атрибутах элементов XSLT. (Примечание: доллар внутри фигурной скобки, потому что полное выражение XPath должно быть заключено в фигурные скобки)

person Aaron Digulla    schedule 11.03.2009
comment
Почему $ должен стоять перед открывающей скобкой? Никогда такого не видел. - person Dirk Vollmar; 11.03.2009
comment
@divo: потому что это синтаксис. - person Welbog; 11.03.2009
comment
(продолжение) В значении атрибута, которое интерпретируется как шаблон значения атрибута [...], можно использовать выражение, окружив его фигурными скобками ({}). - person Dirk Vollmar; 11.03.2009
comment
Ну ты мне показал. Думаю, это то, что я получаю за то, что доверяю ответу на SO. Я больше никогда не совершу эту ошибку! - person Welbog; 11.03.2009
comment
Святые *)%*&/ Я готов поклясться, что это ${} (как и везде). Неудивительно, что XSLT так непопулярен ;) - person Aaron Digulla; 11.03.2009
comment
@divo: Я только что прочитал ссылку и ... я не понял: P Я имею в виду, что это английский и все такое, но ... им все равно, может ли кто-нибудь получить то, что они говорят, не так ли? ;) - person Aaron Digulla; 11.03.2009
comment
@AaronDigulla - Вы были сбиты с толку синтаксисом {$varname}, потому что думали об этом неправильно. $varname - это то, как вы ссылаетесь на переменную. Скобки ограничивают шаблон значения атрибута, содержимое которого может даже не содержать переменной, и в этом случае $ вообще не будет. - person Wayne; 14.12.2011

Используйте <xsl:value-of select="$config"/> вместо {$config}.

person Welbog    schedule 11.03.2009
comment
@Kezzer: Вот почему они платят мне большие деньги ‹('_'‹) - person Welbog; 11.03.2009

Ответ @lwburk отличный (+1), но последний вопрос/ответ точен только для XSLT 1.0 и 2.0. В версии 3.0 вы можете использовать TVT (Шаблон текстового значения; аналогично AVT (шаблону значения атрибута), упомянутому в ответе @lwburk).

Чтобы использовать TVT, добавьте к элементу стандартный атрибут xsl:expand-text="yes". Это заставит процессор рассматривать текстовые узлы-потомки этого элемента как TVT.

Пример:

XSLT 3.0

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <xsl:variable name="who" select="'Dan'"/>
        <xsl:variable name="what" select="'BAM!'"/>
        <result xsl:expand-text="yes">This is {$who}'s result: {$what}</result>
    </xsl:template>

</xsl:stylesheet>

Вывод (используя в качестве входных данных любой правильно сформированный XML)

<result>This is Dan's result: BAM!</result>

Примечание. Протестировано с использованием Saxon-PE 9.5.

person Daniel Haley    schedule 12.05.2014

Потому что вам нужно использовать <xsl:value-of select="config"/> ?

person Kezzer    schedule 11.03.2009
comment
Если config является переменной, мы должны использовать $config, не так ли? - person bortzmeyer; 11.03.2009