Таблицы в несколько колонок в XSLT-шаблонах
Материал из Umicms
Содержание |
Замечание
Если вы столкнулись с этим вопросом и пытаетесь вывести не табличные данные, то следует обратить внимание на использование "плавающих" элементов (например, элементы div с css-свойствами float и min-height). Если этот вариант все-таки не устраивает, тогда можно воспользоваться описанными ниже решениями.
Эти решения также демонстрируют использование осей XPath.
Исходные данные
Есть ответ макроса, например, список объектов каталога:
<udata module="catalog" method="getObjectsList" generation-time="0.302167">− <lines> <item id="42" alt_name="sovet_tc1" link="/shop/sovet_tc1/" xlink:href="upage://42">Sovet TC1</item> <item id="47" alt_name="elektronika_432" link="/shop/elektronika_432/" xlink:href="upage://47">Elektronika 432</item> <item id="50" alt_name="moskwich" link="/shop/moskwich/" xlink:href="upage://50">Moskwich</item> <item id="33" alt_name="televizor_horizont" link="/shop/televizor_horizont/" xlink:href="upage://33">Телевизор «Horizont»</item> <item id="48" alt_name="oki_7" link="/shop/oki_7/" xlink:href="upage://48">Oki 7</item> <item id="43" alt_name="sovet_tc2" link="/shop/sovet_tc2/" xlink:href="upage://43">Sovet TC2</item> <item id="51" alt_name="soviet_b1" link="/shop/soviet_b1/" xlink:href="upage://51">Soviet B1</item> <item id="37" alt_name="televizor_horizont1" link="/shop/televizor_horizont1/" xlink:href="upage://37">Телевизор «LG»</item> <item id="45" alt_name="sovet_tc3" link="/shop/sovet_tc3/" xlink:href="upage://45">Sovet TC3</item> <item id="38" alt_name="televizor_horizont2" link="/shop/televizor_horizont2/" xlink:href="upage://38">Телевизор «Panasonic»</item> <item id="52" alt_name="soviet_ba" link="/shop/soviet_ba/" xlink:href="upage://52">Soviet BA </item> <item id="53" alt_name="soviet_t7" link="/shop/soviet_t7/" xlink:href="upage://53">Soviet T7</item> <item id="39" alt_name="televizor_horizont3" link="/shop/televizor_horizont3/" xlink:href="upage://39">Телевизор «Philips»</item> <item id="40" alt_name="televizor_horizont4" link="/shop/televizor_horizont4/" xlink:href="upage://40">Телевизор «Vityas»</item> </lines> <total>14</total> <per_page>25</per_page> <category_id>31</category_id> <type_id>9</type_id> </udata>
Таблица в 3 колонки
Допустим, мы выводим список объектов каталога из раздела с id = 31. В месте вызова макроса укажем:
<xsl:apply-templates select="document('udata://catalog/getObjectsList/notemplate/31')/udata"/>
Теперь необходимо описать шаблоны обработки результатов макроса:
<xsl:template match="udata[@module = 'catalog'][@method = 'getObjectsList']"> <table> <xsl:apply-templates select="lines/item[position() = 1]|lines/item[position() mod 3 = 1]"/> </table> </xsl:template> <xsl:template match="item"> <tr> <td><xsl:value-of select="."/></td> <td><xsl:value-of select="following-sibling::item[1]"/></td> <td><xsl:value-of select="following-sibling::item[2]"/></td> </tr> </xsl:template>
В первом шаблоне мы выбираем первый элемент item (условие position() = 1), а также каждый следующий 4-й (position() mod 3 = 1).
Второй шаблон выводит элемент tr, внутри которого мы создаем элементы td. В первом элементе td мы выводим значение текущего элемента item при помощи <xsl:value-of select="."/>. Для того, чтобы вывести следующие 2 соседних элемента, мы используем ось following-sibling и указываем, что по этой оси сначала нужно взять 1-й элемент, потом 2-й.
В итоге мы получим следующийх HTML-код:
<table> <tr> <td>Sovet TC1</td> <td>Elektronika 432</td> <td>Moskwich</td> </tr> <tr> <td>Телевизор «Horizont»</td> <td>Oki 7</td> <td>Sovet TC2</td> </tr> <tr> <td>Soviet B1</td> <td>Телевизор «LG»</td> <td>Sovet TC3</td> </tr> <tr> <td>Телевизор «Panasonic»</td> <td>Soviet BA</td> <td>Soviet T7</td> </tr> <tr> <td>Телевизор «Philips»</td> <td>Телевизор «Vityas»</td> <td></td> </tr> </table>
Если мы захотим выводить исходные данные в 4 колонки, необходимо будет изменить условие [position() mod 3 = 1] в первом шаблоне на [position() mod 4 = 1] и придется добавить во второй шаблон еще одну строку:
<xsl:template match="item"> <tr> <td><xsl:value-of select="."/></td> <td><xsl:value-of select="following-sibling::item[1]"/></td> <td><xsl:value-of select="following-sibling::item[2]"/></td> <td><xsl:value-of select="following-sibling::item[3]"/></td> </tr> </xsl:template>
Таблица с произвольным числом колонок
Воспользуемся глобальным параметром, который будет регулировать число колонок. Этот параметр необходимо определять на одном уровне с элементами <xsl:template> непосредственно после тега элемента <xsl:output> (использование глобальных параметров в UMI.CMS позволяет принимать значения из GET-параметров в URL - см. Использование GET и POST параметров в XSLT-шаблонах).
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:param name="colnum" select="3"/> <xsl:template match="/"> ... разметка страницы и вызов макроса как и в первом примере ... </xsl:template> <!-- шаблоны, обрабатывающие ответ макроса и выводящие таблицу--> <xsl:template match="udata[@module = 'catalog'][@method = 'getObjectsList']"> <table> <xsl:apply-templates select="lines/item[position() = 1]|lines/item[position() mod $colnum = 1]"/> </table> </xsl:template> <xsl:template match="item"> <tr> <xsl:apply-templates select=".|following-sibling::item[position() < $colnum]" mode="td"/> </tr> </xsl:template> <xsl:template match="item" mode="td"> <td><xsl:value-of select="."/></td> </xsl:template> <xsl:template match="item[position() = last()]" mode="td"> <td><xsl:value-of select="."/></td> <xsl:if test="position() mod $colnum"> <td colspan="{$colnum - (position() mod $colnum)}"> </td> </xsl:if> </xsl:template> </xsl:stylesheet>
Как и в первом примере, сначала мы выбрали 1-й элемент item и каждый элемент item, позиция которого при делении на $colnum дает остаток 1 (то есть каждый элемент, который должен попасть на новую строку таблицы).
Второй шаблон создает элемент tr, и выбирает текущий элемент item а также необходимое количество его следующих соседей. Здесь мы опять используем ось following-sibling.
Два последних шаблона обрабатывают случаи для всех элементов и для последнего элемента списка. Для последнего элемента необходимо предусмотреть случай, когда число элементов не кратно $colnum - в этом случае мы добавим элемент td с соответствующим значением colspan.
Символьная ссылка   используется вместо сущности, обозначающей неразрывный пробел (см. также Определение сущностей в XSLT-шаблонах)
Теперь, если мы запросим страницу с параметром: http://адрес_сайта/?colnum=4, то получим следующий HTML-код:
<table> <tr> <td>Sovet TC1</td> <td>Elektronika 432</td> <td>Moskwich</td> <td>Телевизор «Horizont»</td> </tr> <tr> <td>Oki 7</td> <td>Sovet TC2</td> <td>Soviet B1</td> <td>Телевизор «LG»</td> </tr> <tr> <td>Sovet TC3</td> <td>Телевизор «Panasonic»</td> <td>Soviet BA</td> <td>Soviet T7</td> </tr> <tr> <td>Телевизор «Philips»</td> <td>Телевизор «Vityas»</td> <td colspan="2"> </td> </tr> </table>
