Логотип

Документация по макросам и шаблонам UMI.CMS

Шаблоны обработки результатов используемых модулей

В предыдущей главе мы определили места в шаблоне разметки страницы, где, при помощи <xsl:apply-templates select="result" />, будем выводить результаты преобразования исходных xml-данных полученных в формате UMI Data.

Теперь перед нами стоят следующие задачи:

  • описать правила проверки соответствия шаблонов (см. также ru.wikipedia.org/wiki/XPath)

  • описать сами шаблоны преобразования в рамках поставленных задач

Лента новостей на главной странице сайта

Правило проверки того, что мы находимся на главной странице сайта можно описать следующим образом: в исходном документе UMI Data у тега page атрибут default должен быть равен "1". Кроме того, мы должны применять это правило только для apply-templates в левой колонке, поэтому необходимо указать mode="leftcol".

Создадим файл ~/xsltTpls/imports/news.xsl и добавим туда следующее:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">



 <xsl:template match="result[page/@is-default = 1]" mode="leftcol">
   <div>
     <h2>Новости</h2>
     <ul id="news">
            
     </ul>
   </div>
 </xsl:template>



</xsl:stylesheet>

Для получения списка последних новостей воспользуемся макросом %news lastlist()%: укажем id лент новостей (предположим, что они равны "3" и "4") и количество новостей равное "3".

Замечание

Следует иметь в виду, что указывая в шаблонах id страниц, мы рискуем работоспособностью шаблона в случаях, когда пользователь случайно удалит страницу. Поэтому, в данном случае, мы можем указать URL страницы, однако, тогда мы должны быть уверены в том, что не возникнет необходимость его поменять.

В этом примере мы рассматриваем другие вопросы, поэтому на этой проблеме мы останавливаться не будем.

Для понимания структуры возвращаемых макросом xml-данных, наберите в адресной строке:

http://ваш_сайт/udata/news/lastlist/(3)(4)/notemplate/3

В полученном ответе нас интересует ветвь items, в которой к каждому элементу item нам необходимо применить уже свой шаблон — для оформления отдельной новости. Поэтому мы вставляем инструкцию apply-templates и описываем дополнительный шаблон для item (для элементов item главной страницы зададим отдельный mode="news.main.item"):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">



 <xsl:template match="result[page/@is-default = 1]" mode="leftcol">
   <div>
     <h2>Новости</h2>
     <ul id="news">
       <xsl:apply-templates select="document('udata://news/lastlist/(3)(4)/notemplate/3')/udata/items" mode="news.main.item" />     
     </ul>
   </div>
 </xsl:template>

 <xsl:template match="item" mode="news.main.item">
   <li>
     
     <div class="date">
        
     </div>
     
     <a href="ссылка на новость">
        
     </a>

     <div>
        <a href="ссылка на блок комментарии на странице полного текста новости">Комментарии</a> 
        ()
     </div>

   </li>
 </xsl:template>



</xsl:stylesheet>

Рассмотрим недостающие блоки по порядку:

  • Дата публикации новости. У каждого элемента item есть атрибут publish_time, значением которого является дата публикации новости в UNIX TIMESTAMP. Поэтому воспользуемся макросом %system convertDate()% и выведем результат с помощью value-of:

    <xsl:value-of select="document(concat('udata://system/convertDate/', @publish_time, '/(d.m.Y)/'))/udata"/>
  • Ссылка на новость. У каждого элемента item есть атрибут link, значением которого является ссылка на полный текст новости:

    <a href="{@link}">
  • Заголовок новости. Выводим содержимое элемента item:

    <xsl:value-of select="." />
  • Ссылка на блок "комментарии" на странице полного текста новости. Воспользуемся ссылкой на якорь, который добавим позднее в шаблон полного текста новости:

    <a href="{@link}#comments">Комментарии</a>
  • Количество комментариев. Воспользуемся макросом %comments countComments()%, которому надо передать id текущей новости. Значение id получим из одноименного атрибута элемента item и выведем результат работы макроса с помощью value-of:

    <xsl:value-of select="document(concat('udata://comments/countComments/', @id))/udata" />

Итоговый шаблон для отображения отдельной новости должен выглядеть следующим образом:

<xsl:template match="item" mode="news.main.item">
  <li>

    <div class="date">
      <xsl:value-of select="document(concat('udata://system/convertDate/', @publish_time, '/(d.m.Y)/'))/udata"/>
    </div>

    <a href="{@link}">
      <xsl:value-of select="." />
    </a>

    <div>
      <a href="{@link}#comments">Комментарии</a> 
          (<xsl:value-of select="document(concat('udata://comments/countComments/', @id))/udata" />)
    </div>

  </li>
</xsl:template>

Меню из названий лент на страницах ленты новостей и страницах полного текста новости

В рамках работы системы UMI.CMS, условие отображения меню из названия лент можно описать очень коротко — отображать меню из лент, если мы получаем страницу от модуля "Новости". Таким образом мы ищем следующее соответствие: в исходном документе UMI Data у тега result атрибут module должен быть равен "news". Кроме того, вывод должен осуществляться в левой колонке, поэтому добавляем mode="leftcol".

Добавим в файл ~/xsltTpls/imports/news.xsl следующее:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


     ...




 <xsl:template match="result[@module = 'news']" mode="leftcol">
   <div>
     
    <h2>
       
    </h2>
   
    <ul>
       
    </ul>
     
   </div>
    
   
    
 </xsl:template>



</xsl:stylesheet>

Рассмотрим недостающие блоки по порядку:

Название страницы, объединяющей все ленты

Предположим, что мы хотим вывести в качестве названия поле h1 для этой страницы и id у этой страницы равен "2". Тогда мы можем получить значение поля, воспользовавшись протоколом Upage. Запросим интересующее нас свойство h1, добавив к запросу ".h1" и выведем результат с помощью value-of:

<xsl:value-of select="document('upage://2.h1')/udata/property/value" />

Структуру возвращаемых xml-данных можно посмотреть, набрав в адресной строке:

http://ваш_сайт/upage/2.h1

Интерактивный список названий лент новостей

Для получения списка лент новостей воспользуемся макросом %news lastlents()%: укажем id страницы раздела, объединяющего ленты ("2"), укажем количество отображаемых названий (предположим, равное "10") и установим значение параметра ignore_paging равное "1" (см. описание макроса).

Для понимания структуры возвращаемых макросом xml-данных, наберите в адресной строке:

http://ваш_сайт/udata/news/lastlents/(2)/notemplate/10/1

В полученном ответе нас интересует ветвь items, в которой к каждому элементу item нам необходимо применить уже свой шаблон — для оформления ссылки с названия ленты. Поэтому мы воспользуемся инструкцией apply-templates и опишем дополнительный шаблон для item (для этого шаблона зададим отдельный mode="news.lents.menu").

Кроме того, нужно предусмотреть варианты "подсветки" текущей ленты, в которой мы в данный момент находимся: либо на странице просмотра ленты, либо на странице просмотра полного текста новости из этой ленты. Для реализации этого вызовем apply-templates с 2 параметрами:

  • URL открытой страницы — значение result/page/@link. Этот параметр понадобится, если мы открыли страницу ленты новостей.

  • Id родительской страницы — значение result/parents/page/@id. Этот параметр понадобится, если мы открыли страницу полного текста новости.

В итоге добавляем вызов шаблона:

<xsl:apply-templates select="document('udata://news/lastlents/(2)/notemplate/10/1')/udata/items" mode="news.lents.menu">
  <xsl:with-param name="thispage-link" select="page/@link"/>
  <xsl:with-param name="parentpage-id" select="parents/page/@id"/>
</xsl:apply-templates>

И добавляем сам шаблон, обрабатывающий каждый элемент item:

<xsl:template match="item" mode="news.lents.menu">
  <param name="thispage-link" />
  <param name="parentpage-id" />
  <li>

   <a href="{@link}">

     <xsl:if test="@link = $thispage-link or @id = $parentpage-id">
       <xsl:attribute name="class">current</xsl:attribute>
     </xsl:if>
   
   <xsl:value-of select="." />
  </a>

  </li>
</xsl:template>

Конструкция <xsl:if>...</xsl:if> проверяет является ли обрабатываемый элемент лентой, страницу которой мы открыли, либо лентой являющейся родительской для открытой страницы. В этих случаях к тегу <a>, содержащему элемент списка, добавляется атрибут class="current", который мы можем описать по своему усмотрению в CSS.

Список рассылок для зарегистрированных пользователей

Сведения о том, кем была открыта страница сайта можно получить, обратившись к элементу user в полученных xml-данных UMI Data. В случае запроса страницы авторизованным пользователем у элемента user появляется атрибут status="auth".

Добавим соответствующий вызов шаблона со своим собственным mode="dispatches.for-auth":

<xsl:apply-templates select="user[@status = 'auth']" mode="dispatches.for-auth" /> 

Этот шаблон мы вынесем в отдельный файл, который мы уже подключили выше к default.xsl. Пример создания рабочих шаблонов рассылок описан в отдельной главе данной документации: Подписка на рассылки с сайта средствами XSLT-шаблонизатора.

Страницы лент новостей

Страницы лент новостей на сайте — это страницы, отображаемые методом rubric модуля "Новости". Следовательно, мы можем задать условие применения шаблона таким образом: match="result[@module = 'news'][@method = 'rubric']".

Однако, здесь мы должны разделить 2 случая: отображение страницы, объединяющей все ленты (можно назвать ее "Все новости"), и страницы архива конкретной ленты. Для разделения этих случаев напишем два условия:

  • страница "Все новости": match="result[@module = 'news'][@method = 'rubric']".

  • архив ленты — убедимся, что это дочерняя страница: match="result[@module = 'news'][@method = 'rubric'][page/@parentId != '0']"

Для получение списка новостей из данной, или нескольких лент воспользуемся макросом %news lastlist()%, которому в одном случае передадим id данной ленты, а во втором нескольких лент (в нашем случае 2). Обработку вывода всего списка новостей мы будем производить одним шаблоном, который мы вызовем, передав id (один или несколько) в качестве параметра.

Добавим в файл news.xsl оба условия:

<xsl:template match="result[@module = 'news'][@method = 'rubric']">
  <xsl:apply-templates select="page" mode="news.lents">
    <xsl:with-param name="lent-id">(3)(4)</xsl:with-param>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="result[@module = 'news'][@method = 'rubric'][page/@parentId != '0']">
  <xsl:apply-templates select="page" mode="news.lents">
    <xsl:with-param name="lent-id" select="page/@id" />
  </xsl:apply-templates>
</xsl:template>

В первом случае мы передаем в качестве параметра id обеих лент, во втором — id открытой страницы, который мы получаем из атрибута id элемента page.

Опишем теперь сам шаблон:

<xsl:template match="page" mode="news.lents">
   
    <h1>
       
    </h1>
    
    
    
    <ul>  
      
    </ul>

    

</xsl:template>

Рассмотрим отдельные блоки по порядку:

Заголовок ленты

Заголовок ленты мы можем узнать из переданных xml-данных UMI Data (в этом шаблоне мы обрабатываем ветку page):

<h1>
  <xsl:value-of select="properties/group/property[@name = 'h1']/value" />
</h1>

Форма подписки для незарегистрированных посетителей сайта

Атрибуты элемента user позволяет узнать, каким пользователем открыта данная страница. Поэтому в этом месте вставим следующую инструкцию:

<xsl:apply-templates select="/result/user[not(@status = 'auth')]" mode="dispatches.for-guest" />

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

Список анонсов новостей

Для получения списка анонсов вызываем макрос %news lastlist()% c переданным параметром и обрабатываем ветку items:

<xsl:apply-templates select="$doc-newspage/udata/items" mode="news.lents" />

Теперь нужно описать шаблон обработки результатов макроса. Ситуация практически аналогичная описанной выше в топике «Лента новостей на главной странице сайта». Отличие заключается в том, что здесь нам нужно отобразить также текст анонса новости, которого нет в ответе макроса.

Поэтому добавим шаблон обработки:

<xsl:template match="item" mode="news.lents">

  <li>
    <div class="date">
      <xsl:value-of select="document(concat('udata://system/convertDate/', @publish_time, '/(d.m.Y)/'))/udata"/>
    </div>

    <a href="{@link}">
      <xsl:value-of select="." />
    </a>

    <div class="anons">
      
    </div>

    <div>
      <a href="{@link}#comments" class="comments">Комментарии</a> 
      (<xsl:value-of select="document(concat('udata://comments/countComments/', @id))/udata" />)
    </div>
  </li>

</xsl:template>

Для получения анонса новости воспользуемся протоколом Upage («Страницы: протокол UPage») — запросим страницу новости, добавив к запросу ".anons," и передадим id обрабатываемого элемента:

<xsl:value-of select="document(concat('upage://', @id, '.anons'))/udata/property/value" disable-output-escaping="yes" />

Если вы хотите, чтобы в анонсах отображалась html-разметка необходимо добавить атрибут disable-output-escaping="yes". Если опустить этот атрибут, все html-теги будут экранированы и отображены как текст.

Постараничный вывод (пейджинг)

Реализация простейшего постраничного вывода описана в отдельной статье: Постраничный вывод (пейджинг) стредствами XSLT-шаблонизатора.

Страница полного текста новости

Правило проверки того, что мы находимся на странице отображения полного текста новости описывается следующим образом — это страница возвращаемая методом item модуля "Новости". Таким образом правило выбора шаблона можно описать следующим образом: match="result[@module = 'news' and @method = 'item'].

Поэтому добавляем шаблон:

<xsl:template match="result[@module = 'news' and @method = 'item']">
    
  <h1>
    
  </h1>
    
  <div id="new">
  
    <div class="date">
           
    </div>
  
    <div class="content">
      
    </div>
  
        

    <h3><a name="comments">Комментарии</a></h3>
    
    
   
    <h3><a name="addcomment">Добавить комментарий</a></h3>
    
        

  </div>

  </xsl:template>

Рассмотрим недостающие блоки по порядку:

Заголовок новости

Заголовок новости — это значение элемента value ветки property c атрибутом name='h1':

<h1>
  <xsl:value-of select="page/properties/group/property[@name = 'h1']/value" />
</h1>

Дата публикации новости

Дата публикации доступна в ветке property с атрибутом name="publish_time" у элемента value в значении атрибута unix-timestamp формата UMI Data. Для вывода ее в нужном нам формате, как и на главной странице сайта и на страницах лент, воспользуемся макросом %system convertDate()%:

<div class="date">
  <xsl:value-of select="document(concat('udata://system/convertDate/', page/properties/group/property/value/@unix-timestamp, '/(d.m.Y)/'))/udata"/>
</div>

Полный текст новости

Полный текст новости — это контент страницы новости. Поэтому мы выведем значение элемента value ветки property с атрибутом name="content" формата UMI Data:

<div class="content">
  <xsl:value-of select="page/properties/group/property[@name = 'content']/value" disable-output-escaping="yes"/>
</div>

Здесь также обратите внимание на атрибут disable-output-escaping="yes", который в данном случае необходим для отображения html-разметки текста новости.

Источник новости

Здесь надо предусмотреть несколько возможных вариантов, под которые мы напишем отдельные шаблоны:

  • Источника новости может не быть — ничего не выводим (например, если ваш сайт и есть источник).

  • Источник новости может быть ссылкой: либо с названия, либо просто ссылка на сайт-источник.

  • Источник новости может быть просто текстом (оффлайн-источник).

В формате UMI Data есть два элемента, отвечающих за текст ссылки, и за саму ссылку: это элемент property с атрибутом name="source" и элемент property с атрибутом name="source_url".

Добавим правило применения шаблонов с условием, что хотя бы один из этих элементов присутствует и со своим собственным mode="news.source":

<xsl:apply-templates select="page/properties/group[property[@name = 'source' or @name = 'source_url']]" mode="news.source" />

Теперь опишем шаблоны для каждого случая:

  • Есть текст ссылки и сама ссылка:

    <xsl:template match="group[property[@name = 'source'] and property[@name = 'source_url']]" mode="news.source">
      <div class="newitem-source">
      Источник:&nbsp;
        <a href="{./property[@name = 'source_url']/value}">
          <xsl:value-of select="./property[@name = 'source']/value" />
        </a>
      </div>
    </xsl:template>
  • Есть текст, но нет ссылки (оффлайн-источник):

    <xsl:template match="group[property[@name = 'source'] and not(property[@name = 'source_url'])]" mode="news.source">
      <div class="newitem-source">
        Источник:&nbsp;
        <xsl:value-of select="./property[@name = 'source']/value" />
      </div>
    </xsl:template>
  • Есть ссылка, но нет текста ссылки. Тогда продублируем поле — сделаем ссылку текстом:

    <xsl:template match="group[not(property[@name = 'source']) and property[@name = 'source_url']]" mode="news.source">
      <div class="newitem-source">
        Источник:&nbsp;
        <a href="{property[@name = 'source_url']/value}">
          <xsl:value-of select="property[@name = 'source_url']/value" />
        </a>
      </div>
    </xsl:template>

Список добавленных комментариев

Для отображения списка комментариев воспользуемся макросом %comments insert()%, которому мы передадим id страницы полного текста новости, полученный из значения одноименного атрибута элемента page:

<xsl:apply-templates select="document(concat('udata://comments/insert/', page/@id))/udata" mode="comments.list" />

Пример работающих шаблонов отображения списка комментариев можно посмотреть в главе: Комментарии средствами XSLT-шаблонизатора.

Отображение формы добавления комментария

Поскольку мы хотим предусмотреть разные варианты форм для зарегистрированных пользователей сайта, и для гостей, то применим инструкцию apply-templates по ветке user и передадим в качества параметра id страницы:

<xsl:apply-templates select="user" mode="comments.add">
  <xsl:with-param name="page-id" select="page/@id"/>
</xsl:apply-templates>

Описание самих шаблонов отображения форм описано в отдельной главе, посвященной модулю "Комментарии": Комментарии средствами XSLT-шаблонизатора.