Применение другого шаблона XSLT в зависимости от параметра - PullRequest
6 голосов
/ 08 апреля 2011

Что у меня есть?

У меня есть проект ASP.NET, в котором у меня есть файл XSLT с множеством определенных шаблонов.Только один шаблон будет использоваться одновременно в зависимости от выбора пользователя для отображения содержимого на веб-странице.Это выглядит примерно так:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:param name="TemplateName"></xsl:param>

      <xsl:template match="Title_Only">
          ...template Title_Only body...
      </xsl:template>

      <xsl:template match="Image_Only">
          ...template Image_Only body...
      </xsl:template>

      <xsl:template match="Title_And_Image">
          ...template Title_And_Image body...
      </xsl:template>
    </xsl:stylesheet>

Что я хочу?

Я хочу передать имя шаблона TemplateName в качестве параметра и иметь возможность применитьсоответствующий шаблон на данных.

Может кто-нибудь подскажите, пожалуйста, как мне этого добиться?

Ответы [ 3 ]

6 голосов
/ 08 апреля 2011

Вы не можете использовать значение параметра или переменной в шаблоне соответствия в XSLT 1.0.Однако вы можете условно применять шаблоны из одного шаблона, например:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="TemplateName"/>
    <xsl:template match="/">
        <xsl:apply templates select="something[some_condition=$TemplateName]"/>
    </xsl:template>
</xsl:stylesheet>

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

Пример условного применения шаблонов

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="TemplateName" select="'Title_Only'" />
    <xsl:template match="/">
        <xsl:apply-templates select="test/val[@name=$TemplateName]" />
    </xsl:template>
    <xsl:template match="val">
        <xsl:value-of select="@name" />
    </xsl:template>
</xsl:stylesheet>

Примененона этот вход:

<test>
    <val name="Title_Only" />
    <val name="Image_Only" />
    <val name="Title_And_Image" />
</test>

Производит:

Title_Only

... на основе значения $TemplateName.(Обратите внимание, что в этом примере используется переменная, но идея та же.)

Отдельные шаблоны с использованием режимов

Если вам действительно нужен совершенно другой шаблон в каждом случае, затем используйте режимы.Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="TemplateName" select="'Title_Only'" />
    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="$TemplateName='Title_Only'">
                <xsl:apply-templates select="test/val" mode="Title_Only" />
            </xsl:when>
            <xsl:when test="$TemplateName='Image_Only'">
                <xsl:apply-templates select="test/val" mode="Image_Only" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="test/val" mode="Title_And_Image" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="val" mode="Title_Only">
        <xsl:value-of select="@title" />
    </xsl:template>
    <xsl:template match="val" mode="Image_Only">
        <xsl:value-of select="@img" />
    </xsl:template>
    <xsl:template match="val" mode="Title_And_Image">
        <xsl:value-of select="@title" />/
        <xsl:value-of select="@img" />
    </xsl:template>
</xsl:stylesheet>

Применительно к этому источнику:

<test>
    <val title="some title" img="some image"/>
</test>

Производит:

some title

Используется нужный шаблон, основанный на значении параметра.

2 голосов
/ 08 апреля 2011

Я хочу передать имя шаблона TemplateName в качестве параметра и будет возможность применить соответствующий шаблон на данные.

В XSLT 1.0 и XSLT 2.0 запрещено иметь такую ​​конструкцию, как:

<xsl:call-template name="{$vTemplateName}"/>

Хотя в XPath 3.0 (XSLT 3.0) представлены функциональные элементы и HOF (функции высшего порядка), HOF можно эмулировать в предыдущих версиях XSLT. Для получения дополнительной информации прочитайте статьи на главной странице FXSL .

Вот упрощенный пример идеи, лежащей в основе FXSL :

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

Учитывая этот пример XML, у нас есть два шаблона, один из которых выдает сумму всех элементов num, а другой производит их конкатенацию. Мы хотим передать желаемую операцию в качестве параметра.

Вот как это сделать (обратите внимание, что в самом исходном XML ничего не говорит нам, какую операцию использовать):

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

 <xsl:param name="pOp" select="'sum'"/>

 <my:ops>
  <op>sum</op>
  <op>concat</op>
 </my:ops>

 <xsl:variable name="vOps" select=
   "document('')/*/my:ops/*"/>

 <xsl:template match="/">
  <xsl:apply-templates select="$vOps[. = $pOp]">
   <xsl:with-param name="arg1" select="/*/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="op[.='sum']">
  <xsl:param name="arg1"/>
  <xsl:value-of select="sum($arg1)"/>
 </xsl:template>

 <xsl:template match="op[.='concat']">
  <xsl:param name="arg1"/>

  <xsl:for-each select="$arg1">
   <xsl:value-of select="."/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

При применении к XML-документу выше, желаемый, правильный результат получается:

55

при замене :

 <xsl:param name="pOp" select="'sum'"/>

с

 <xsl:param name="pOp" select="'concat'"/>

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

01020304050607080910

Обратите внимание :

Основной (использующий) шаблон может и обычно находится в отдельном файле таблицы стилей XSLT и будет импортировать таблицы стилей с шаблонами, которые реализуют операции. Основной шаблон не знает, какие операции реализованы (и не использует <xsl:choose> с жестко закодированными именами).

Фактически, если шаблоны добавляются или удаляются из импортированных файлов, нет необходимости изменять основной (используя) шаблон. В этом стиле программирования команда <xsl:apply-templates> часто выбирает для шаблонов выполнения, которые еще не были написаны, когда был создан основной шаблон.

1 голос
/ 08 апреля 2011

Присоединяйтесь к атрибуту mode в элементе .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...