В рубрике CMS - верстка, на момент написания статьи Верстка элементов центрального контента был сделан каркас будущей CMS и сверстана центральная часть нашей системы. Теперь сделаем тоже самое, но уже с использованием технологии XML / XSLT.
Для начала необходимо определиться что мы будем преобразовывать с помощью технологии XSLT и во что мы это будем преобразовывать. Вообще, XSLT - это технология, позволяющая преобразовывать XML-документ в другой XML-документ, HTML-документ, PDF-документ, просто текст и т.д. Из википедии: «При применении таблицы стилей XSLT, состоящей из набора шаблонов, к XML-документу (исходное дерево) образуется конечное дерево, которое может быть другой XML-структурой, HTML-документом или обычным текстом. Правила выбора (и, отчасти, преобразования) данных из исходного дерева пишутся на языке запросов XPath».
Таким образом для начала нам необходим XML-документ. Где его взять? Вся информация у нас хранится в базе данных (ну, это у нас). Надо взять эту информацию и оформить ее в виде XML-документа, и делать это будем мы в недалеком будущем на стороне сервера с помощью PHP. А сейчас предположим, что мы уже имеем XML-документ следующего вида:
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type='text/xsl' href='index.xsl'?> <root> <header> <exit href="http://www.fancode.ru/">Выход на сайт</exit> <fio>ФИО пользователя</fio> </header> <menu> <folders> <folder>Страницы сайта</folder> <links> <link href="#">Каталог страниц</link> <link href="#">Новости</link> </links> </folders> <folders> <folder>Настройки</folder> <links> <link href="#">Пользователи</link> <link href="#">Группы пользователей</link> <link href="#">Настройки</link> <link href="#">Изменение пароля</link> </links> </folders> </menu> <title_table>Заголовок таблицы</title_table> <pagination> <select> <sel>5</sel> <sel>10</sel> <sel>20</sel> <sel>50</sel> </select> </pagination> <tbody> <tr> <count>1</count> <name>Страница 1</name> <desc>Название 1</desc> <inner>0</inner> <on_off>0</on_off> <show href="#">0</show> <edit href="#">0</edit> <dell>0</dell> </tr> <tr> <count>2</count> <name>Страница 2</name> <desc>Название 2</desc> <inner>1</inner> <on_off>1</on_off> <show href="#">0</show> <edit href="#">0</edit> <dell>0</dell> </tr> <tr> <count>3</count> <name>Страница 3</name> <desc>Название 3</desc> <inner>1</inner> <on_off>1</on_off> <show href="#">0</show> <edit href="#">0</edit> <dell>0</dell> </tr> </tbody> <footer> </footer> </root>
Комментарии к XML-коду:
- вторая строка - подключение XSLT-файла со стилями;
- содержимое тега header - данные заголовка;
- содержимое тега menu - данные меню, где folders - раздел меню, folder - заголовок раздела, links - группы ссылкок меню и link - ссылки;
- pagination - постраничная навигация;
- в теге table_tr - содержимое центрального контента;
- и footer - подвал.
Теперь рассмотрим XSLT-файлы со стилями, приводящие данные XML к нужному виду . Сначала подключается index.xsl:
<?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" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/> <xsl:include href="main.xsl"/> <xsl:template name="thead"> <tr class="header"> <th class="center" width="40px">№</th> <th class="left">Название</th> <th class="left" width="160px">Виртуальный каталог</th> <th class="center" width="30px">Вл.</th> <th class="center" width="30px">Пок.</th> <th class="center" width="30px">См.</th> <th class="center" width="30px">Ред.</th> <th class="center" width="30px">Уд.</th> </tr> </xsl:template> <xsl:template match="tbody"> <xsl:apply-templates select="tr"/> </xsl:template> <xsl:template match="tr"> <tr class="tr_body"> <td class="center"><input id="sort_" name="sort[]" type="text" class="t_text small_text" value="{normalize-space(count)}" /></td> <td class="left"><xsl:value-of select="name"/></td> <td class="left"><xsl:value-of select="desc"/></td> <xsl:if test="inner=0"> <td class="center"><a href="#" title="Нет вложенных страниц или каталогов"><img src="img/forward_off.gif" alt="Нет вложенных страниц или каталогов" width="15" height="12"/></a></td> </xsl:if> <xsl:if test="inner=1"> <td class="center"><a href="#" title="Перйти к вложеннм страницам или каталогам"><img src="img/forward.gif" alt="Перйти к вложеннм страницам или каталогам" width="15" height="12"/></a></td> </xsl:if> <xsl:if test="on_off=0"> <td class="center"><a href="#" title="Включить"><img src="img/off.gif" alt="Включить" width="15" height="15"/></a></td> </xsl:if> <xsl:if test="on_off=1"> <td class="center"><a href="#" title="Выключить"><img src="img/on.gif" alt="Выключить" width="15" height="15"/></a></td> </xsl:if> <td class="center"><a href="{@href}" target="_blank" title="Просмотреть страницу"><img src="img/edit_pages_thumb.png" alt="Просмотреть страницу" width="16" height="16"/></a></td> <td class="center"><a href="#" title="Редактировать"><img src="img/fileexport.png" alt="Редактировать" width="16" height="15"/></a></td> <td class="center"><input id="dell[]" name="dell[]" type="checkbox" value="" /></td> </tr> </xsl:template> </xsl:stylesheet>
В этом файле, после объявления заголовков, формата вывода и DOCTYPE результирующего документа идет строка подключения основного шаблона main.xsl. Ниже находится именованный шаблон для оформления заголовков таблицы thead и шаблон для тела таблицы tbody, в котором, для каждого элемента исходного XML-файла tbody вызывается шаблон для строки таблицы tr. Таким образом в index.xsl находятся изменяемые данные - заголовки столбцов и строки таблицы.
Код основного шаблона main.xsl:
<?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" /> <xsl:include href="header.xsl"/> <xsl:include href="menu.xsl"/> <xsl:include href="pagination.xsl"/> <xsl:include href="btn.xsl"/> <xsl:include href="footer.xsl"/> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Верстка CMS с помощью технологии XML / XSLT</title> <link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="table.css" /> <link rel="stylesheet" type="text/css" href="tree.css" /> <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="js/jquery.simple.tree.js"></script> <script type="text/javascript" src="js/table.js"></script> </head> <body> <div class="container"> <!-- header --> <xsl:apply-templates select="/root/header"/> <!-- menu --> <xsl:apply-templates select="/root/menu"/> <!-- content --> <div id="cont_admin_content"> <div id="admin_content" class="admin_content"> <div id="admin_content" class="admin_content"> <!-- title table --> <div class="path"><xsl:value-of select="/root/title_table"/></div> <!-- pagination --> <xsl:apply-templates select="/root/pagination"/> <table class="maintable" cellspacing="1"> <!-- thead --> <thead> <xsl:call-template name="thead"/> </thead> <!-- tbody --> <tbody id="admin_table_body"> <xsl:apply-templates select="/root/tbody"/> <xsl:call-template name="btn"/> </tbody> </table> </div> </div> <!-- footer --> <xsl:apply-templates select="/root/footer"/> </div> </body> </html> </xsl:template> </xsl:stylesheet>
Вначале идет подключение файлов с шаблонами шапки, меню, постраничной навигации, кнопок управления и подвала нашей CMS. Далее формируется HTML-документ, где в разделе HEAD подключаются CSS стили и JavaScript. В теле страницы с помощью правил apply-templates и call-template происходит подключение соответствующих шаблонов.
Последнее, что осталось рассмотреть, это шаблоны шапки, меню, постраничной навигации, кнопок управления и подвала.
XSLT-шаблон шапки header.xsl, который пожалуй не требует комментарив:
<?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" /> <xsl:template match="header"> <div id="header"> <p class="menu_top"> <a id="id_admin_exit" href="{exit/@href}"><xsl:value-of select="exit"/></a> </p> <h1>FAN<span>CODE</span>.CMS</h1> <p class="person_top"> Пользователь: <span class="fiospan"> <xsl:value-of select="fio"/> </span> </p> </div> </xsl:template> </xsl:stylesheet>
XSLT-шаблон меню menu.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="menu"> <div id="menu_left"> <div class="top"></div> <div class="midle"> <ul class="simpleTree"> <li class="root"> <span><a id="id_main_menu" href="#/main_menu" class="admin_menu_on first_a">Главная страница</a></span> <ul class="first_ul"> <xsl:apply-templates select="/root/menu/folders"/> </ul> </li> </ul> </div> <div class="bottom"></div> </div> </xsl:template> <xsl:template match="folders"> <xsl:if test="position()=1"> <li class="open"> <span> <xsl:value-of select="folder"/></span> <ul> <xsl:apply-templates select="links"/> </ul> </li> </xsl:if> <xsl:if test="position()!=1"> <li> <span> <xsl:value-of select="folder"/></span> <ul> <xsl:apply-templates select="links"/> </ul> </li> </xsl:if> </xsl:template> <xsl:template match="links"> <xsl:apply-templates select="link"/> </xsl:template> <xsl:template match="link"> <li><span> <a href="{@href}" class="admin_menu_off"><xsl:value-of select="."/></a></span></li> </xsl:template> </xsl:stylesheet>
HTML-код берем из статьи Делаем основное меню. Внутри списка ul class="first_ul" задаем правило apply-templates select="/root/menu/folders", которое обращается к шаблону folders, в котором происходит проверка на номер позиции элемента в списке, и если позиция равна 1, то элементу списка присваивается CSS - стиль "open". Это необходимо, чтобы в первая папка меню при загрузке страницы была открытой. Далее применяем правило apply-templates select="links", и к каждому элементу списка links применяется правило преобразования template match="link". В итоге получаем требуемый вид меню.
XSLT-шаблон постраничной навигации и поиска pagination.xsl:
<?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" /> <xsl:template match="pagination"> <table class="maintable" cellspacing="1"> <tr class="pag"> <td class="td_form_show_str"> Показать: <select class="aselect" id="select_pag" > <xsl:for-each select="/root/pagination/select/sel"> <option value=""><xsl:value-of select="."/></option> </xsl:for-each> </select> </td> <td class="td_pagination_page"><div id="Pagination" class="pagination" >Постраничная навигация</div></td> <td class="td_field_search"> <p><span class="search" style="float:left"> </span> <input type="text" class="text_field corner-all" name="search" id="search" value="" /> </p> </td> <td class="center"><a href="#" title="Обновить страницу" class="reset"> </a></td> </tr> </table> </xsl:template> </xsl:stylesheet>
XSLT-шаблон кнопок управления btn.xsl:
<?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" /> <xsl:template name="btn"> <tr class="tr_body tr_border_top"> <td colspan="5"></td> <td class="center"><a href="#" title="Добавить" ><img src="img/add.png" alt="Добавить" width="22" height="22"/></a></td> <td class="center"><a href="#" title="Сохранить все" ><img src="img/save_all.png" alt="Сохранить все" width="22" height="22"/></a></td> <td class="center"><a href="#" title="Удалить выделенное" ><img src="img/delete.png" alt="Удалить выделенное" width="22" height="22"/></a></td> </tr> </xsl:template> </xsl:stylesheet>
И наконец, XSLT-шаблон подвала footer.xsl:
<?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" /> <xsl:template match="footer"> <div id="admin_footer"> <p><!-- содержимое footer --></p> </div> </xsl:template> </xsl:stylesheet>
Подведем итоги.
Чего мы добились. В первую очередь - это полное разделение данных и представления. В этом заключается основное преимущество преобразования XML с помощью технологии XSLT. Действительно, данные могут формироваться на сервере каким угодно способом, с помощью любого языка программирования, может использоваться любая база данных, а дальше формируется документ XML, соответствующий общепринятому стандарту и посылается браузеру. Т.е. для XSLT - преобразования не важен источник данных.
В данной статье приведены лишь простейшие операции с помощью технологии XSLT. В следующих статьях будут рассмотрены примеры более продвинутого использования этой технологии.