Обычно конструкцию вида xsl:copy-of
используют для копирования фрагмента исходного дерева в результирующее дерево. При этом забывая, что xsl:copy-of
можно использовать для копирования фрагмента результирующего дерева. Вроде бы, польза от этого неочевидна, однако, я покажу, как это можно применить.
Допустим, у нас есть верстка какого-то сложного html-блока, причем этот блок может повторяться во многих местах, но с разным контентом. В качестве примера рассмотрим блок с закругленными углами, так как обычно это достаточно сложная html-конструкция, состоящая из нескольких html-элементов:
<div class="rounded">
<div class="corner l-t"></div>
<div class="corner r-t"></div>
<div class="corner r-b"></div>
<div class="corner l-b"></div>
<div class="content">
<!-- контент -->
</div>
</div>
И мы хотим обрамлять такой конструкцией свои блоки, допустим — статьи, формы, меню. Решение в лоб — в шаблоне вывода каждого такого блока добавлять такую обрамляющую конструкцию. Т.е. «копипаст» со всеми вытекающими из него последствиями.
Примерно, это выглядело бы так (возьмем блок статей):
<xsl:template match="articles">
<div class="rounded">
<div class="corner l-t"></div>
<div class="corner r-t"></div>
<div class="corner r-b"></div>
<div class="corner l-b"></div>
<div class="content">
<xsl:apply-templates select="article"/>
</div>
</div>
</xsl:template>
Мой вариант — создать для обрамляющей html-конструкции отдельный именованный шаблон, а контент передавать ему параметром, который внутри шаблона копировать с помошью xsl:copy-of
:
<xsl:template name="block">
<xsl:param name="content"/>
<div class="rounded">
<div class="corner l-t"></div>
<div class="corner r-t"></div>
<div class="corner r-b"></div>
<div class="corner l-b"></div>
<div class="content">
<xsl:copy-of select="$content"/>
</div>
</div>
</xsl:template>
Шаблоны соответствующих блоков (статей, форм, меню) будут выглядеть следующим образом:
<xsl:template match="articles">
<xsl:call-template name="block">
<xsl:with-param name="content">
<xsl:apply-templates select="article"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="navigation">
<xsl:call-template name="block">
<xsl:with-param name="content">
<ul class="navigation">
<xsl:apply-templates select="navigation-item"/>
</ul>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="form">
<xsl:call-template name="block">
<xsl:with-param name="content">
<xsl:apply-templates select="." mode="zforms"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
Получилось, что шаблоны ничего не знают о том окружении, в котором будет находиться сгенерированный ими контент. Таким образом, вводится дополнительный уровень абстракции, отделяющий содержание от представления. Все вышенаписанное — это всего лишь один пример, как можно применить подобный подход, который можно использовать и для более сложных случаев.
P.S. Впервые похожую идею я когда-то услышал от Владимира Токмакова из Студии.
3 комментария:
видел еще на миксньюзе. понравилось, пользую, бывает)
(вазда)
Использую подобный подход для передачи html’а в шаблон, который его эскейпит в js-строку.
Кстати, если вам вдруг понадобится заблокировать чей-то сотовый телефон или другое средство связи, то воспользуйтесь для этого Блокираторы мобильных телефонов.
Отправить комментарий