|
|
dkLab | Конструктор | Dklab_ShortXSLT: упрощенный синтаксис для XSLT с операторами вставки, if, else и т. д.
2009-02-28
Помочь с разработкой и улучшением библиотеки можно на GitHub.
Библиотека Dklab_ShortXSLT это система поддержки упрощенного синтаксиса XSLT для встроенных в PHP классов XSLTProcessor и DOMDocument. Фактически это компилятор с диалекта XSLT в стандартный XSLT, запускаемый "на лету" и "прозрачно" для вызывающего кода (естественно, с кэшированием результата компиляции, поэтому накладные расходы минимальны). Подключить Dklab_ShortXSLT к существующему проекту на XSLT можно, написав несколько дополнительных строчек кода. Dklab_ Синтаксис Dklab_ShortXSLTОбычный синтаксис XSLT весьма громоздок, что оказывается неудобным при его использовании в Web-программировании. Библиотека позволяет облегчить эту проблему. Сравним стандартный XSLT с возможностями Dklab_ShortXSLT. Фигурные скобки вне тэгов: {xpath}Конструкцию "фигурные скобки" вида
Или любое другое выражение XPath:
Вставка значения языковой константы: {#const_name}В многоязычных проектах, да и просто там, где тексты сайта выделены в отдельное хранилище, удобно ссылаться на них через "языковые константы".
Языковые константы с параметрами: {#const_name(param)}Иногда в текст константы нужно вставить некоторое значение. Например, если
языковая константа
Или даже так:
Условный оператор: {if} ... {elseif} ... {else} ... {/if}В XSLT условный
Цикл for-each: {for-each}Хотя for-each и не является громоздким оператором, для полноты картины он также поддерживается.
Вызов именованного шаблона: {call-template}Блоки некоторого HTML-макета иногда удобно оформиить в виде именованных XSLT-шаблонов. Шаблоны затем вызываются через xsl:call-template там, где нужно вставить соответствующий блок.
Автоматическая генерация exclude-result-prefixesОбычно элемент <xsl:stylesheet> содержит определение нескольких пространств имен, которые, если ничего не предпринять, попадают в результирующий HTML-документ, засоряя его. С этим можно бороться, перечисляя префиксы пространств имен в атрибуте exclude-result-prefixes элемента <xsl:stylesheet>. Однако очень легко пропустить какой-то из префиксов и не заметить этого. Dklab_ShortXSLT добавит атрибут exclude-result-prefixes в <xsl:stylesheet> за вас.
Остальные
|
| Листинг 1: Подключение Dklab_ShortXSLT |
// Создаем препроцессор ShortXSLT с поддержкой языковых констант и exclude-result-prefixes.
$preproc = new Dklab_ShortXSLT("Dictionary::get", true);
// Создаем XSLT-документ и привязываем к нему препроцессор.
$xslDoc = new Dklab_DOMDocument();
$xslDoc->addPreprocessor(array($preproc, "process"));
// Устанавливаем директорию для кэширования.
$xslDoc->setCacheDir('/tmp/Dklab_ShortXSLT');
// Загружаем XSLT-шаблон.
$xslDoc->load('page.xsl');
// Передаем его XSLT-процессору.
$xsl = new XSLTProcessor();
$xsl->registerPHPFunctions();
$xsl->importStyleSheet($xslDoc);
// ...
// Далее используем $xsl для генерации HTML-страниц обычным способом. |
Под конец рассмотрим пример работы с библиотекой (посмотреть результаты его работы).
| Листинг 3: PHP-обработчик: page.php |
<?php
require_once dirname(__FILE__) . '/../../lib/config.php';
require_once dirname(__FILE__) . '/../../Dklab_DOMDocument/lib/config.php';
require_once "Dklab/DOMDocument.php";
require_once "Dklab/ShortXSLT.php";
// Create ShortXSLT preprocessor with constant and
// exclude-result-prefixes support.
$preproc = new Dklab_ShortXSLT("Dictionary::get", true);
// Load XSLT template and assign the preprocessor.
$xslDoc = new Dklab_DOMDocument();
$xslDoc->addPreprocessor(array($preproc, "process"));
// Set cache directory. ATTENTION! It is not safe to set this
// directory in /tmp on shared (non-dedicated) hosting, because
// all web-server users may see and modify it. Use your own,
// secure path instead of /tmp.
$xslDoc->setCacheDir('/tmp/Dklab_ShortXSLT');
$xslDoc->load('page.xsl');
// Initialize the XSLT processor and assign the template.
$xsl = new XSLTProcessor();
$xsl->setParameter("", "debug", intval(@$_GET['debug']));
$xsl->registerPHPFunctions();
$xsl->importStyleSheet($xslDoc);
// Run the transformation.
$doc = new DOMDocument();
$doc->loadXML('<root><name>Vasily Pupkin</name></root>');
echo $xsl->transformToXML($doc);
/**
* Dictionary: implement site localization logic.
* Holds keys and corresponding text messages for substitutions.
*/
class Dictionary
{
/**
* A dictionary is commonly load from outside. But we place
* it here for demo purposes only.
*/
private static $_dictionary = array(
'MENU' => "Menu",
'MAIN' => "Main page",
'PAGE' => "Test page",
'HELLO' => "Good morning, %s!",
'SITE_NAME' => "Test site",
);
/**
* This function is an XSLT constant request callback.
* Each time ShortXSLT sees "#xxx" reference in the template,
* it replaces this reference to call to the preprocessor.
* It works even within templates included via xsl:include
* and xsl:import.
*/
static function get()
{
$args = func_get_args();
$key = array_shift($args);
if (!@$_GET['debug']) {
$value = isset(self::$_dictionary[$key])?
self::$_dictionary[$key] : "#{$key}#";
if ($args) {
$value = vsprintf($value, $args);
}
} else {
$value = "[ORIG:$key]";
}
return $value;
}
}
echo "<br><br><hr>";
show_source(__FILE__); |
| Листинг 4: Главный шаблон страницы: page.xsl |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:import href="1_layout.xsl" /> <xsl:template name="body"> {#HELLO(/root/name)} <h2> {if $debug != 0} <a href="page.php">Replace keys by TEXTS</a> {else} <a href="page.php?debug=1">Debug mode: show KEYS</a> {/if} </h2> </xsl:template> </xsl:stylesheet> |
| Листинг 5: Включаемый шаблон макета: 1_layout.xsl |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:template match="/"> <html> <head><title>{#SITE_NAME}</title></head> <body> <div style="padding:6px; border: 2px solid black"> {#MENU}: {for-each document('1_menu.xml')/menu/item} <a href="{@url}">{.}</a> <xsl:text> </xsl:text> {/for-each} </div> <br/> <xsl:call-template name="body" /> </body> </html> </xsl:template> </xsl:stylesheet> |
Конечно, Dklab_
См. также другие продукты и стандарты, посвященные сокращению синтаксиса XSLT (к сожалению, среди них нет ни одного решения для PHP):