Предположим, что шаблон страницы, где мы хотим отобразить формы добавления и список комментариев, выглядит следующим образом (пример шаблона для страницы полного текста новости):
// news.item
<xsl:template match="result[@module = 'news'][@method = 'item']">
// правила отображения контента; рассматривать не будем
<h3><a name="comments">Комментарии</a></h3>
// здесь мы хотим увидеть список комментариев
// здесь мы отобразим форму добавления новых комментариев
</xsl:template>
Для отображения списка комментариев воспользуемся макросом %comments insert()%, передав ему id текущей страницы. Например в приведенном выше шаблоне это будет значение атрибута id
элемента page
ответа UMIData (см. «Формат UMI Data»).
Поэтому мы можем написать инструкцию apply-templates
для обработки результатов макроса, построив запрос при помощи функции concat()
и подключив результаты макроса при помощи функции document()
:
<xsl:apply-templates select="document(concat('udata://comments/insert/', page/@id))/udata"/>
Ответ макроса в формате UData можно посмотреть, набрав в адресной строке: http://адрес_сайта/udata/comments/insert/id_страницы_с_комментариями
Для отображения формы добавления нового комментария нам нужно учесть случаи с зарегистрированными пользователями и гостями сайта (мы будем показывать им разные формы). Поэтому добавим apply-templates
и выберем элемент user
ответа UMIData, который описывает пользователя, открывшего текущую страницу:
<xsl:apply-templates select="user"/>
В зависимости от содержимого элемента user
мы и будем выводить под списком комментариев разные формы.
Теперь осталось только описать сами шаблоны для списка комментариев и вывода форм.
Вариант, когда комментарии отсутствуют опишем так (менее специфичный шаблон, он будет выбран "по-умолчанию"):
<xsl:template match="udata[@module = 'comments'][@method = 'insert']">
<span>Нет комментариев</span>
</xsl:template>
Условие [@module = 'comments'][@method = 'insert']
указывает, что это шаблон должен быть применен для обработки результатов макроса %comments insert()%.
В случае, когда присутствуют комментарии, в XML-ответе макроса будут ветви items
с вложенными элементами item
, и мы можем обработать список при помощи следующего шаблона:
<xsl:template match="udata[@module = 'comments'][@method = 'insert'][items/item]">
<xsl:variable name="doc-numpages" select="document(concat('udata://system/numpages/', total, '/', per_page, '/notemplate/p/10'))/udata" />
<ul class="comments">
<xsl:apply-templates select="items/item" mode="comments.list" />
</ul>
<xsl:apply-templates select="$doc-numpages" mode="paging.words" /> // utils.xsl
<xsl:apply-templates select="$doc-numpages" mode="paging.numbers" /> // utils.xsl
</xsl:template>
Условием [@module = 'comments'][@method = 'insert'][items/item]
указывает, что этот шаблон должен быть применен для обработки результатов макроса %comments insert()% с элементами item
вложенными в items
.
Можно видеть также, что в этом шаблоне уже подключен пейджинг, пример создания которого можно посмотреть в отдельной главе: Постраничный вывод (пейджинг) стредствами XSLT-шаблонизатора. Параметры total
и per_page
для макроса %system numpages()% уже содержатся в ответе макроса %comments insert()%.
Место, куда будет выведен список комментариев указан инструкцией apply-templates
, которая выбирает каждый элемент item
из ответа макроса, описывающий отдельный комментарий из списка, и применяет к ним шаблоны. Для оформления внешнего вида каждого комментария опишем такой шаблон:
<xsl:template match="item" mode="comments.list">
<li>
<xsl:value-of select="@num" />.
<span class="title">
<xsl:value-of select="@title" />
</span>
-
<xsl:apply-templates select="document(concat('udata://users/viewAuthor/', @author_id))/udata"/>
<div class="message">
<xsl:value-of select="." disable-output-escaping="yes" />
</div>
</li>
</xsl:template>
Для получения данных об авторе комментария мы воспользовались макросом %users viewAuthor()%, которому передали в качестве параметра значение атрибута author_id
элемента item
.
Шаблоны оформления автора можно дополнить самостоятельно (см. XML-ответ макроса %users viewAuthor()%), ниже приводится простейший вариант создания ссылки с электронным адресом автора:
<xsl:template match="udata[@module = 'users'][@method = 'viewAuthor']">
<xsl:value-of select="nickname" />
</xsl:template>
<xsl:template match="udata[@module = 'users'][@method = 'viewAuthor'][email]">
<a class="author" href="mailto:{email}">
<xsl:value-of select="nickname" />
</a>
</xsl:template>
Если автор не указал свой e-mail, будет выбран первый шаблон и выведен только nickname
. Если в ответ макроса присутствует элемент email
будет задействован второй шаблон (с условием [email]
), который подставит его значение в ссылку после слова "mailto:".
Создадим два шаблона, описывающих вывод формы для зарегистрированных пользователей и гостей сайта.
Случай авторизованного автора описывает следующее условие match="user[@status = 'auth']"
, поэтому шаблон может выглядеть следующим образом:
<xsl:template match="user[@status = 'auth']">
<h3><a name="addcomment">Добавить комментарий</a></h3>
<form method="post" action="/comments/post/{/result/@pageId}/" name="form_addcomment" id="form_addcomment">
<fieldset class="intext">
<label for="comment_title" id="for_title" title="Заголовок">
<span>Заголовок: <sup class="asterisk">*</sup></span>
<input type="text" name="title" id="comment_title" />
</label>
<label for="comment_text" id="for_comment" title="Текст">
<span>Текст: <sup class="asterisk">*</sup></span>
<textarea name="comment" id="comment_text" cols="6" />
</label>
</fieldset>
<input class="submit-send" type="submit" value="Отправить"/>
</form>
</xsl:template>
За отправку комментария отвечает метод post
модуля "Комментарии", которому мы передаем id страницы, на которой мы выводим форму (id страницы находится, например, в атрибуте pageId
тега result
). Пары атрибут-значение name="title"
и name="comment"
для полей ввода являются обязательными, так как в ином случае метод comments/post
не обработает эти данные.
Случай Гостя описывается менее специфичным условием соответствия — match="user"
. Кроме того, необходимо предусмотреть вариант скрытия формы, в случае запрета в настройках модуля оставлять комментарии для незарегистрированных пользователей. Макрос %comments insert()% в этом случае не отобразит элементы action
в своем ответе, чем мы и воспользуемся.
Создадим следующий шаблон:
<xsl:template match="user">
<xsl:apply-templates select="document(concat('udata://comments/insert/', /result/@pageId))/udata/action"/>
</xsl:template>
Мы передали макросу %comments insert()% id текущей страницы таким же образом, что и ранее, и выбрали элемент action
для того, чтобы построить форму добавления комментария. Теперь необходимо создать шаблон, который будет обрабатывать элемент action
и в итоге выводить форму:
<xsl:template match="action">
<h3><a name="addcomment">Добавить комментарий</a></h3>
<form method="post" action="{.}" name="form_addcomment" id="form_addcomment">
<fieldset class="intext">
<label for="comment_title" id="for_title" title="Заголовок">
<span>Заголовок: <sup class="asterisk">*</sup></span>
<input type="text" name="title" id="comment_title" />
</label>
<label for="comment_author">
<span>Ваш ник:</span>
<input type="text" name="author_nick" id="comment_author" />
</label>
<label for="comment_email">
<span>Ваш e-mail:</span>
<input type="text" name="author_email" id="comment_email" />
</label>
<label for="comment_text" id="for_comment" title="Текст">
<span>Текст: <sup class="asterisk">*</sup></span>
<textarea name="comment" id="comment_text" cols="6" />
</label>
</fieldset>
// здесь мы хотим отобразить капчу
<input class="btt submit-send" type="submit" value="отправить"/>
</form>
</xsl:template>
Значение action для формы находится в элементе action
, который обрабатывает этот шаблон. Поэтому его можно вывести просто указав {.}
(точка — означает текущий элемент).
Здесь также следует обратить внимание на то, что пары атрибут-значение name="title"
, name="author_nick"
, name="author_email"
, name="comment"
для полей ввода являются обязательными, иначе метод post
не обработает эти данные.
Осталась последняя задача — реализовать вывод CAPTCHA (защитного кода). Для этого мы воспользуемся макросом %system captcha()%. Этот макрос возвращает URL картинки с защитным кодом и случайную строку, которую можно добавить к адресу картинки, чтобы избежать кэширования браузерами. Добавим в место отображения картинки следующее:
<xsl:apply-templates select="document('udata://system/captcha')/udata[url]" />
Добавим также следующее описание шаблона:
<xsl:template match="udata[@module = 'system'][@method = 'captcha']">
<fieldset>
<legend>Введите символы защиты от автосозданий <sup class="asterisk">*</sup></legend>
<label for="captcha" id="for_captcha" title="Защитный код">
<div class="input">
<input type="text" name="captcha" id="captcha" />
</div>
<span><img src="{url}{@random_string}" /></span>
</label>
</fieldset>
</xsl:template>
Значение элемента url
— это адрес картинки, а атрибут random_string
, это случайная строка вида "?1255523102". Пара атрибут-значение name="captcha"
необходима для метода post
, обрабатывающего форму.