использование xsl в качестве шаблона страницы

jer

...
использование xsl в качестве шаблона страницы

подскажите плиз, я что-то торможу...

пишу конструктор сайтов с использованием xml и xslt. возникла следующая проблема:

1. есть xml-файл с данными текущей страницы
2. есть xsl-файл-шаблон для всех страниц сайта (либо какой-то группы страниц)
3. есть xsl-файл для текущей страницы

xsl-файл-шаблон содержит что-то типа:

<html>
<head>
</head>
<body>
.. какой-то html код...
[здесь идет встравка куска template1 из xsl-файла текущей страницы]
...какой-то html код...
[здесь идет встравка куска template2 из xsl-файла текущей страницы]
...какой-то html код...

...

[здесь идет встравка куска templaten из xsl-файла текущей страницы]
...какой-то html код...

</body>
</html>

т.е. в шаблоне есть места куда должны вставляться куски текущей страницы из xsl-файла.

как реализовать эти вставки при помощи xslt?

ps: надеюсь вопрос понятно изложил...
 

Flying

Guest
Изложил понятно, но вот XSLT ты абсолютно не знаешь и просто понятия не имеешь, как он работает. Очень советую сходить на www.zvon.org и почитать XSLT Tutorial.
 

jer

...
похоже всетаки не совсем понятно изложил, т.к. представление имею о xslt, не говорю что идеально им владею, но ...

попробую подругому пояснить...

конкретная html страница сайта генерируется путем xslt-преобразования.

а xslt-файл формируется (должен формироваться) из двух xslt-кусков (берущихся из базы).

один кусок - это шаблон всех страниц в котором есть "дырки" (например n=3)
другой кусок - это n=3 xslt-кусков которые должны вставляться в те самые "дырки" в xslt-шаблоне.

ну и собственно xml-файл с данными

сорри если я туплю, но чую что тут все элементарно, что голова уже пухнет от этой системы... отдохнуть чтоли... ;)
 

Flying

Guest
Ну теперь понятно. Странная система, прямо скажем.... Но непонятно становится другое - если ты собираешь XSLT для преобразования - зачем производить эту сборку также при помощи XSLT? Нет, это конечно можно сделать - вставь на эти места какие-нибудь специальные теги, сформируй XML из кусков и напусти на него XSLT, который для заданных тегов будет делать <xsl:copy-of> нужного куска. Но не легче ли будет сделать str_replace() ? :)
 

jer

...
ну почему же странная?

если на всех страницах изменяется только центральная часть и правая колонка (например), то зачем в xslt-файле каждой страницы дублировать эту информацию?

вот и возникла идея делать xslt-шаблоны для группы похожих страниц.

а почему я хочу все это средствами xslt делать, это чтобы не плодить разные там замены, т.к. пользователь будет задавать дизайн страницы в виде xslt, если его еще затавлять в шаблоне вставлять спец.ссылки на другие xslt-куски, то это будет уже не чистый xslt, да я просто был уверен что xslt это все позволяет делать, вот и спросил...

я тоже уже начал подумывать о том, чтобы сначала формировать xml, а потом xslt на него напускать, но это мне кажется много рессурсов сожрет, вот и ищу более простой (быстрый) выход.

или ты предлагаешь как-нибудь подругому решить эту задачу?
 

Flying

Guest
а что такое <xsl:include> и <xsl:import> - ты знаешь?

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

jer

...
да, знаю, но они позволяют включать другие файлы, а мне требуется вставлять узел из текущего xslt-файла. можно было эти xslt-куски делать в виде отдельных файлов и инклудить, как ты предлагаешь, но у меня все генерится динамически, не из файлов, а из базы берутся xslt-куски и собирается xslt-файл, но он даже на диск не пишется, хранится в переменной в памяти.

я понимаю что это функциональный язык, может я что-то не так понимаю... , но тогда объясни, плиз, как мне решить мою задачу.

может моя задача немного не вписывается в xslt?
 

IchPokhudezh

Guest
jer, к примеру, вы можете написать скрипт, отдающий XSL-документ из базы. Потом с помощью xsl:import/xsl:include объедините шаблоны.
 

Flying

Guest
2jer:
В качестве несколько извращенного решения могу предложить реализовать собственную схему (scheme).
Смотреть здесь:
http://www.php.net/manual/en/function.xslt-set-scheme-handler.php

Скажу сразу - сам не пробовал, но сам принцип решения вполне рабочий.
 

Sababa

Guest
может моя задача немного не вписывается в xslt?
твой _подход_ не вписывается в xslt.

Опиши задачу и думаю, что сам увидишь другое решение, либо люди подскажут то, что нужно будет.

А, вообще, к вопросу как решить задачу по вставке некоторого куска в xml или xslt (не имеет значения), то есть такие штуки как entities либо более продвинутая штука XInclude. Как этим пользоваться рассказывать не буду. (2jer: поверь, твою задачу можно и нужно решить другим способом)
 

jer

...
2chameleon: я в дом xslt не загоняю, да и не хочу из-за такой мелочи достаточно ресурсоемкую операцию делать (понятно что это все равно потом происходит, но вроде у меня доступа к дереву нету при моем варианте обработки xml). а пихаю на вход саблотрону таким образом:

PHP:
  $xh = xslt_create();
  $arguments = array('/_xml' => $xml,'/_xsl' => $xslt);
  $html = @xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
2IchPokhudezh: вариант с инклюдами пожалуй и придется применить я чувствую. придется хранить xslt в виде файлов на диске, а не в базе как сейчас. мне казалось что инклудить "дороже" чем брать узлы из текущего файла. но раз такой возможности получается нету, то это гнилая затея ;)

2Flying: спасибо конечно, но пока постараюсь обойтись без "извращений" ;)

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

2[DAN]: спасибо за ссылку, почитал, как раз то что мне надо, почти.

пока остановился на include. а по ресурсоемкости это сильно жадная функция?
 

Flying

Guest
пока остановился на include. а по ресурсоемкости это сильно жадная функция?
Не особо, хотя Sablotron иногда занимается некими непонятными вещами, жрущими время при выолнении include. Я писал об этом разработчикам (http://archive.gingerall.cz/archives/public/sablot2002/msg01984.html), но ответа так и не получил.

А по поводу "извращений" - зря ты, думаю это именно то, что тебе нужно, заодно и поэкспериментировал бы.
 

jer

...
Flying, я посмотрел xslt_set_scheme_handler, но не свосем понял как с ней обращаться? примеров нигде не нашел...
 

Flying

Guest
Автор оригинала: jer
Flying, я посмотрел xslt_set_scheme_handler, но не свосем понял как с ней обращаться? примеров нигде не нашел...
Точно не знаю :)

Но принцип таков, что ты регистрируешь функцию-обработчик для схемы, например "my://" и потом, когда в XSLT ты пишешь:

<xsl:include href="my://file.xsl"/>

Должна вызваться твоя функция, в которой ты можешь делать что хочешь - лишь бы возвратил XSLT документ :)
Причем эту схему можно использовать в любом месте, где используется URL, т.е. например в document() - тоже.
Я знаю, что в приложениях на Java этот прием очень широко применяется, но на PHP сам не пробовал.
 

jer

...
вот некоторый пример приближенный к моей задаче:
PHP:
<?php

// XML - контент
$xml = '<?xml version="1.0" encoding="Windows-1251"?> 
<page>
  <newslist>
    <news id="1"><date>2003-02-02</date><name>первая новость</name><desc>текст новости 1</desc></news>
    <news id="2"><date>2003-02-04</date><name>вторая новость</name><desc>текст новости 2</desc></news>
    <news id="3"><date>2003-02-07</date><name>третья новость</name><desc>текст новости 3</desc></news>
  </newslist>
  <article>
    <name>название статьи</name>
    <text>текст статьи</text>
    <author>Иванофф</author>
  </article>
</page>';

// XSL - шаблон
$xsl_template = '<?xml version="1.0" encoding="windows-1251"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" encoding="Windows-1251"/> 
<xsl:template match="/">
    <xsl:apply-templates/> 
</xsl:template>
<xsl:template match="page">
  <html>
    <head>
      <title>test</title>
    </head>
    <body>
      <table border="1" width="100%" height="100%">
        <tr>
          <td colspan="2" height="100">
            шапка
          </td>
        </tr>
        <tr>
          <td width="200">
  <xsl:apply-templates select="newslist"/>
          </td>
          <td>
<!-- сюда надо вставлять кусок из текущей страницы -->
  <xsl:value-of select="document(\'template:tpl1\')"/>
          </td>
        </tr>
      </table>
    </body>
  </html>
</xsl:template>
<xsl:template match="newslist/news">
  <small><xsl:value-of select="date"/></small> - 
  <b><xsl:value-of select="name"/></b>
  <p><xsl:value-of select="desc"/></p>
</xsl:template>
</xsl:stylesheet>'; 


// XSL - текущая странциа:
$xsl_cur = '
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" encoding="Windows-1251"/> 
<xsl:template match="article">
  <h1><xsl:value-of select="name"/></h1>
  <p><xsl:value-of select="text"/></p>
  автор: <xsl:value-of select="author"/>.
</xsl:template>
</xsl:stylesheet>
';

// обработчик
function handGetAll($processor,$scheme,$rest) 
{
  global $xsl_cur;
  if (($scheme == "template") && ($rest == "/tpl1"))
  {
    return $xsl_cur;
  }
}

$xh = xslt_create();
xslt_set_scheme_handlers($xh,array("get_all" => "handGetAll"));
echo xslt_process($xh,'arg:/_xml', 'arg:/_xsl',NULL,array("/_xml"=>$xml,"/_xsl"=>$xsl_template)); 
xslt_free($xh);

?>
но если вставлять путем
<xsl:value-of select="document(\'template:tpl1\')"/>
то вставляется значение, а шаблоны дальше не обрабатываются. можно конечно сначала парсить каждый вставляемый кусок отдельно, а потом вставлять просто как значение, но это изврат ИМХО.

2Flying: а include и import можно использовать только на верхнем уровне (в корне xslt-документа), так что для моего случая не удается их применять.

ps: еще... вставляемых кусков может быть несколько, не обязательно один как в этом примере.
 

jer

...
в общем я разобрался, обошелся без xslt_set_scheme_handlers. просто в местах вставки вазываю обработку всего xml документа но с другим режимом (mode). т.е. все эти вставки у меня разграничиваются по mode.
все оказалось куда проще чем я думал, да и ничего лишнего мудрить не пришлось с разбором дерева. все уложилось в стандартный xslt. спасибо всем за участие в дискуссии...
 
Сверху