Это пример немного более сложного для понимания меню, поэтому для начала рекомендуется ознакомиться с топиком «Меню в виде списка». Кроме того, в этом примере будет использоваться протокол UPage (см. «Страницы: протокол UPage») и возможности сокращенного вызова по этому протоколу.
Предположим, что у нас уже есть шаблоны, описанные в предыдущем разделе — «Меню в виде списка» и мы представляем как они работают.
Наша задача, задействовать в шаблоне меню поля, содержащие путь до изображений активного и неактивного элемента меню (см. также «Общие сведения»).
Предположим, что мы хотим получить HTML-код следующего вида для списка элементов меню:
<ul>
<li>
<a href="/page1/">
<img src="/images/cms/data/page1.jpg">Название страницы 1
</a>
</li>
<li>
<a href="/page2/">
<img src="/images/cms/data/page2.jpg">Название страницы 2
</a>
</li>
<li>
<a href="/page3/" class="active">
<img src="/images/cms/data/page3_act.jpg">Название страницы 3
</a>
</li>
</ul>
Итак, если посмотреть в пример предыдущего меню, мы видим, что 1 шаблон обрабатывают активный пункт меню, и 1 — все остальные.
Для того чтобы выводимые страницы, содержали ссылку на изображения для активного или неактивного пункта меню, необходимо добавить изображения в админке для этих страниц в поля "Изображение активного раздела" и "Изображение неактивного раздела" соответственно.
После того, как изображения туда добавлены, каждая из этих страниц при запросе ее как XML данные (см. «Страницы: протокол UPage») будет содержать ссылки на эти 2 изображения в элементах:
-
property
с атрибутомname="menu_pic_a"
— для изображения активного раздела -
property
с атрибутомname="menu_pic_ua"
— для изображения неактивного раздела
Таким образом, задача сводится к получению значений этих элементов и вставке их в атрибут src
тега <img>
Для того, чтобы получить значение отдельного свойства для страницы, не обязательно вызывать ее полностью в виде XML-данных. Можно воспользоваться сокращенными вызовами ():
-
например, upage://94.menu_pic_a — для изображения активного раздела
-
и upage://94.menu_pic_ua — для изображения неактивного раздела
В результате мы получим XML-данные следующего содержания:
<udata generation-time="0.008246">
<property id="28" name="menu_pic_a" type="img_file">
<title>Изображение активного раздела</title>
<value path="./images/cms/data/148820_pic1.jpg" folder="/images/cms/data" name="148820_pic1" ext="jpg" width="450" height="372">
/images/cms/data/148820_pic1.jpg
</value>
</property>
</udata>
Поскольку протокол UPage возвращает XML-данные, включить эти данные в обработку можно при помощи функции document()
. Кроме того, на самом деле в этой задаче нас интересует только содержимое элемента value
— то есть можно записать включения следующим образом (предположим, что id страницы 94):
-
document('upage://94.menu_pic_a')/udata/property/value — для изображения активного раздела
-
document('upage://94.menu_pic_ua')/udata/property/value — для изображения неактивного раздела
Теперь вернемся к шаблону, обрабатывающему отдельный пункт меню:
<xsl:template match="item" mode="menu">
<li>
<a href="{@link}">
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
Вспомним теперь как выглядит ответ макроса — %content menu()% (см. в описании ответ UData). Отдельный элемент item
ответа макроса уже содержит идентификатор страницы в своём атрибуте id
:
<item id="95" link="/page1/" name="Название страницы 1" xlink:href="upage://95">
Передав этот параметр из шаблона в запрос UPage мы и получим ссылку на изображение для каждого пункта меню.
Для того чтобы построить такой запрос необходимо воспользоваться еще одной функцией XSLT — concat()
.
Вставить полученное значение в атрибут src
тега <img>
мы можем таким же способом как мы вставляли атрибут link
в href
для ссылки ранее.
Таким образом получаем шаблон для неактивного пункта:
<xsl:template match="item" mode="menu">
<li>
<a href="{@link}">
<img src="{document(concat('upage://', @id, '.menu_pic_ua'))/udata/property/value}"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
И шаблон для активного пункта:
<xsl:template match="item[@status = 'active']" mode="menu">
<li>
<a href="{@link}" class="active">
<img src="{document(concat('upage://', @id, '.menu_pic_a'))/udata/property/value}"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
Замечание
Следует иметь в виду, что использование этих шаблонов не учитывает того, что картинки для некоторых страниц может и не быть. В таком случае в итоговом HTML-коде будут теги <img>
с пустым src
. Решение этой проблемы описано ниже.
Для того, чтобы тег <img>
вставлялся только тогда, когда есть значение в соответствующих полях у запрошенных страниц, мы опишем еще один шаблон, который будет обрабатывать результаты запроса.
Как и во всех предыдущих примерах обработку будет производить при помощи apply-templates
, выбрав (select
) для обработки элемент value
:
<xsl:template match="item" mode="menu">
<li>
<a href="{@link}">
<xsl:apply-templates select="document(concat('upage://', @id, '.menu_pic_a'))/udata/property/value" mode="menu"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
Теперь необходимо описать шаблон, который должен примениться к элементу value
и вставить его значение в атрибут src
тега <img>
. Укажем шаблон при помощи соответствия match="value".
Режим mode="menu"
позволит обработать именно этот вызов и не спутать с другими возможными вызовами в шаблонах.
Сам шаблон чрезвычайно прост (однако в зависимости от реальных задач его можно дополнить всем, чем необходимо):
<xsl:template match="value" mode="menu">
<img src="{.}" />
</xsl:template>
Запись {.}
говорит шаблонизатору о том, что нужно вставить содержимое текущего обрабатываемого элемента — в нашем случае содержимое value
.
В случае, если этого элемента в ответе UPage нет — инструкция apply-templates
ничего не отправит на обработку, и шаблон не будет активирован. Соответственно, тег <img>
в таком случае не будет выведен.
Как уже было сказано выше, если мы гарантированно выводим изображения для каждого пункта меню, и все их заранее задали — достаточно будет таких шаблонов:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="html" indent="yes"/>
<xsl:template match="/">
<html>
<head></head>
<body>
<div class="menu">
<xsl:apply-templates select="document('udata://content/menu/')/udata"/>
</div>
<div class="content">
</div>
</body>
</html>
</xsl:template>
<xsl:template match="udata[@module = 'content'][@method = 'menu']">
<ul>
<xsl:apply-templates select="items/item" mode="menu"/>
</ul>
</xsl:template>
<xsl:template match="item" mode="menu">
<li>
<a href="{@link}">
<img src="{document(concat('upage://', @id, '.menu_pic_ua'))/udata/property/value}"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
<xsl:template match="item[@status = 'active']" mode="menu">
<li>
<a href="{@link}" class="active">
<img src="{document(concat('upage://', @id, '.menu_pic_a'))/udata/property/value}"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
</xsl:stylesheet>
В случае, если вывод пустого тега <img>
для пунктов меню, у которых не заданы эти поля, нежелателен — предлагается следующий набор шаблонов:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="html" indent="yes"/>
<xsl:template match="/">
<html>
<head></head>
<body>
<div class="menu">
<xsl:apply-templates select="document('udata://content/menu/')/udata"/>
</div>
<div class="content">
</div>
</body>
</html>
</xsl:template>
<xsl:template match="udata[@module = 'content'][@method = 'menu']" mode="menu">
<ul>
<xsl:apply-templates select="items/item" mode="menu"/>
</ul>
</xsl:template>
<xsl:template match="item" mode="menu">
<li>
<a href="{@link}">
<xsl:apply-templates select="document(concat('upage://', @id, '.menu_pic_a'))/udata/property/value" mode="menu"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
<xsl:template match="item[@status = 'active']" mode="menu">
<li>
<a href="{@link}" class="active">
<xsl:apply-templates select="document(concat('upage://', @id, '.menu_pic_a'))/udata/property/value" mode="menu"/>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:template>
<xsl:template match="value" mode="menu">
<img src="{.}" />
</xsl:template>
</xsl:stylesheet>