Решение проблем обработки XSLT на стороне клиента

XSLT*
Вы уже используете XSLT в качестве шаблонизатора на сервере. Настал черёд перенести xsl-трансформацию на клиента. Можно, например, воспользоваться способом описанным в статье На клиенте! Получить XML! Получить XSL! Сделать XHTML! Марш!. Но это было бы слишком просто, потому что каждый браузер добавляет несколько своих нюансов при работе с XSLT.

Вопросы о способе загрузки xsl- и xml-файлов и их обработки в различных браузерах был рассмотрен в указанной выше статье. Рассмотрим другие вопросы:
1) инклудинг;
2) кеширование;

Все примеры опубликованы на этой странице ra-project.net/xsl_tests/ и работают в браузерах Opera, Chrome, IE6, Firefox, Safari.

Инклудинг


Простая инструкция вида
<xsl:include href="common/forms.xsl"/>,
которая превосходно работает в случае xsl-трансформации на сервере, при разборе в некоторых браузерах не будет корректно обработана. Все браузеры смогут подгрузить дополнительный xsl-файл если к нему указан полный URL. Например такой:
<xsl:include href="http://site.com/xsl/common/forms.xsl"/>.

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

В примере "Тест инклудинг" обрабатывается одинарный инклуд. Здесь основной xsl-файл 1.xsl подгружает дополнительный файл-разметки 1_1.xsl.

В примере "Тест двойной инклудинг" обрабатывается двойной инклуд. Здесь основной xsl-файл 2.xsl подгружает 2_1.xsl, который в свою очередь обращается к ещё одному xsl-файлу 1_1.xsl.

Кеширование


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

Иначе поступает IE. Он кеширует эти данные раз и навсегда (на продолжительное время), так что даже после обновления страницы браузер будет в твёрдой уверенности, что ранее загруженные файлы не потеряли своей актуальности. Единственный вариант обновить данные — очистить кеш браузера вручную.

Поэтому если нам необходимо, чтобы на сайте отображались актуальные данные, которые приходят к нам в виде xml, то необходимо дописывать постфикс. Например так ra-project.net/xsl_tests/res/1.xml?_1234567890666. А само кеширование реализовать на javascript. То же касается и файлов-трансформации. Например, на этапе разработки, мы хотим чтобы наш браузер всегда оперировал «свежей» версией xsl-файла, а на продакшине можно даже позволить браузеру закешировать этот xsl-файл.

В примере "Тест инклудинг" можно «поиграть» настройками кеширования. Результаты работы настроек можно пронаблюдать с помощью средств отладки: Firebug, Dragonfly, Developer Tools.

Использованные инструменты


Для xsl-трансформации на стороне клиента, я использовал плагин к jQuery Transform, в котором были добавлены функции кеширования и доработан механизм инклудинга. Доработаный вариант можно взять здесь ra-project.net/xsl_tests/jquery.transform.js.

Не рассмотренные вопросы


Остались ещё 2 не рассмотренных вопроса:
1) отладка при ошибках загрузки и трансформации;
2) проблема обработки инструкции disable-output-escaping=«yes» в firefox.
О них в другой раз.

UPD. Реальный работающий пример использования данной техники.
juick.ra-project.net/stats#ra
Здесь выводится статистика постов по месяцам. При клике на определённый месяц подгружаются xml-данные месяца и xsl-файл. Причём xsl-файл будет загружен лишь один раз. А xml-данные кешируются, поэтому если «гулять» по списку месяцев, то однажды загруженные данные не будут вновь браться с сервера, а возьмутся из кеша.
+27
18 октября 2010, 14:19
61
Holden 11,7

комментарии (40)

+1
N1k1t0ZzZ #
А чем вызвана необходимость проведения преобразований именно на стороне клиента? Или это синтетический пример?

Просто интересуюсь =)
+2
Inquirer #
Разгрузка сервера. Клиентские мощности позволяют.
–2
N1k1t0ZzZ #
Разгрузка сервера — спору нет.

А вот «Клиентские мощности позволяют» — тут все будет зависеть от объема данных, специфики и сложности структуры, особенно в связи с популярностью нетбуков и прочих мобильных устройств.

Впрочем возможно я несколько субъективен в силу того, что сам никогда трансформации на клиента не переносил.
+4
Holden #
Реальный пример. Имеем список пользователей. Их можно просматривать и править.

В обычной версии это выглядело бы так. Список пользователей (1 запрос). Кликаем на пользователя — грузится страница с инфой об пользователе (1 запрос на список юзеров + 1 запрос на данные юзера), кликаем изменить — грузится страница с формой редактирования (1 запрос на список юзеров + 1 запрос на данные юзера). Итого 5 запросов.

В случае xml/xsl. Имеем список пользователей (1 запрос). По клику на пользователя подгружаются данные пользователя в xml (1 запрос) и трансформация для представления этих данных в xsl. Кликаем на изменить — подгружается только xsl, содержашая инфу о форме редактирования. А xml с данными он уже загружен и его повторно грузить не надо. Подгружаемые xsl будут закешированы браузером. Итого 2 запроса.

Не всегда, но иногда так даже проще реализовать функционал.
0
N1k1t0ZzZ #
Резонно, спасибо за полезную статью =)
0
maxatwork #
А еще можно для редактирования/валидации/сохранения разные моды использовать. Тогда xsl один только раз нужно будет загрузить. И данные можно сразу префетчить по всем пользователям (если массовое редактирование, например, планируется), если, конечно, сервер считает, что текущий пользователь их может просматривать.
0
s0rr0w #
Пока данные лежали на стороне клиента, они обновились на стороне сервера. Ведь доступ к данным может быть для более чем одного пользователя. И ваша суперстройная система рушится, потому что при сохранении вы запишите старые данные. А чтобы это не случилось, придется наворотить непростой механизм валидации данных. Так что не факт, что вы выиграете в итоге.
+1
Holden #
В стандартной схеме та же ситуация. Пока один админ редактирует профиль юзера, другой админ в это время уже изменил этот же профиль.
–1
s0rr0w #
Но отслеживать такие действия проще.
+1
stas_agarkov #
какие проблемы? пиши в форму timestamp и при выполнении запроса проверяй нет ли в базе более нового timestamp
а системе управления проектами trac это так реализовано
0
stas_agarkov #
то, что я описал, у вас называется непростым механизмом валидации данных :)))
0
LeshaL #
Не нужно никакой логики на сервере. Т.е. вообще серверная часть сводится к запуску httpd

Пример (у нас так документация устроена): документы (XML) лежат под системой контроля версий. И XSL документы лежат тоже там. Нужно добавить новый документ — берешь шаблон (ссылки на XSL файлы в нем есть), забиваешь данными и кидаешь под версионинг. При просмотре через веб (либо локально по файловым урл-ам) открывается не XML, а его преобразованый в HTML вид. С другой стороны, эти же самые данные могут поступать на вход компьютеризированной системы. Соотвественно: теже файлы по тем же урл-ам скачиваются как просто XML-документы, но никуда не преобразуются, а обрабатываются скриптами.
+2
maxatwork #
Да ладно, одними статическими документами не всегда можно обойтись — не все пользователи хорошо относятся к редактированию данных в XML =)
0
LeshaL #
Ну пользователи-то да. Речь идет о документации QA отдела в IT компании )
0
tenshi #
а они чем провинились?
+1
iamo0 #
AJAX-ом. Если на сервере используется XSLT, удобно будет использовать одни и те же шаблоны для вывода чего-нибудь сервером, а потом для динамической подгрузки AJAX-ом.

Про разгрузку ничего говорить не буду, это довольно странно разгружать сервер за счет пользователя, лучше уж пусть сервер потупит, чем потом драгоценного пользователя мучить.
0
Holden #
Не надо никого мучить. XSLT-преобразования в браузерах работают быстро. И не надо придумывать дополнительных шаблонизацый в виде smarty на javascript'е (во это точно будет работать медленнее).
+1
s0rr0w #
Даже на страницах в пару мегабайт?
–1
Holden #
Это стоит проверить.
0
tenshi #
я как-то делал документацию. там на базе сравнительно небольшой xml-ки строилась красивая хтмл-лина. так вот, парсинг 2 маленьких хмл-ок и создание большой хтмл-ины — это гораздо быстрее, чем парсинг гигантской хтмл-ины с перерисовкой 2 раза в секунду.
0
s0rr0w #
Охотно поверю. Но как будут обстоять дела с большой xml'иной?
0
tenshi #
всяко лучше чем со столь же большой хтмл-иной
0
Galyna #
Автору респект!
0
tenshi #
1) инклудинг;
не надо делать инклудинг — надо собирать все шаблоны в 1-2 файла и отдавать скопом

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

2) проблема обработки инструкции disable-output-escaping=«yes» в firefox.
а нафиг она?

0
Holden #
1) считаю это мнение ошибочным. Работа с шаблонами на стороне клиента не должна отличаться от такой же работы на стороне сервера. Другими словами — на стороне сервере ник-то же не собирает все шаблоны в один?

2) Шаблоны — да должны кешированться браузером. Я уже описал, когда такое поведение браузера является вредным. Данные же наоборот — в большинстве случаев не должны кешироваться, за некоторыми исключениями.

3) проблема просто существует в этом браузере. А решить её нужно для того, чтобы пользователь получал то, что ожидает увидеть.
0
tenshi #
1. собирают. и скрипты собирают. даже файловую систему дёргать лишний раз накладно, что уж говорить про удалённые сервера

2. ты не умеешь его готовить просто ;-) habrahabr.ru/blogs/client_side_optimization/90481/

3. xss уязвимость? х)
0
Holden #
1) пожалуйста пример какой-либо такой системы (cms, фреймвокр или что-нибудь)
2) спасибо за ссылку
3) уязвимости нет.
0
tenshi #
1. dklab.ru/chicken/nablas/49.html
3. докажи
0
Holden #
1) про объединение шаблонов ни слова.
3) я говорю об этом https://bugzilla.mozilla.org/show_bug.cgi?id=98168. При чём здесь xss?
0
tenshi #
1. осспади, ну вот пример с шаблонами view-source:http://mojura.110mb.com/?xsl:main
2. я знаю. эта фича будет использоваться пользователями для вывода сырого хтмл-а в подавляющем большинстве случаев толком не отфильтрованного. не надо им давать гранату
0
b0n3Z #
А насколько xslt+xml производительнее js-шаблонизатора+json? И вообще, как вы считаете, что оптимальнее?
0
Holden #
Цифрами доказать не могу, но считаю, что xslt будет работать быстрее. Потому что для обработки шаблона xslt будет использоваться сам шаблон + xslt-процессор браузера. Для обработки js-шаблона потребуются: сам шаблон + js-код + интерпритатор js-кода. А интерпритаторы всегда работают медленнее, чем нормальный скомпиленный код.
+1
nikitammf #
Цифрами уже все посчитано.
На последнем я субботнике Степан Резников читал доклад Шаблонизация на клиенте, в котором в конце приведены цифры, так вот js-шаблонизация( в частности Micro-Templating от John Resig) работает быстрее XSLT.
И еще один плюс, на мной взгляд, js-шаблонизации более простой способ хранения темплейтов.
0
bdiang #
Действительно, какой смысл использовать xslt, если нет выигрыша в производительности? Кроме того, нативный яваскрипт в шаблонах куда понятнее и удобнее, чем синтаксис xslt шаблонов.
0
Holden #
В случае с js-темплейтом мы вместо одного шаблона имеем два. И если вносятся изменения в один шаблон, то надо править и другой.
На счёт понятности — дело привычки. Если достоточно поработать с xslt, то понимаешь всё его удобство и все его возможности по стравнению с «обычными» шаблонами.
0
bdiang #
О каких двух шаблонах идет речь? К примеру шаблон Micro-Templating:

<% for ( var i = 0; i < users.length; i++ ) { %>
    <li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
  <% } %>


все просто и понятно, и никакого второго шаблона ему не надо.

Мое имхо, json + шаблон с нативным синтаксисом, это удобнее, чем xml + xslt.

>> Если достоточно поработать с xslt, то понимаешь всё его удобство и все его возможности по стравнению с «обычными» шаблонами.

А в чем заключается эти удобство и возможности?
0
Holden #
2 шаблона:
1) шаблон для генерации контента на стороне сервера
2) для генерации контента на стороне клиента.
0
bdiang #
Ну, в этом плане да. Но я рассматривал только с точки зрения клиента.
+1
klen #
Очень интересно как к построенным по такому принципу сайтам относятся поисковики? Насколько я себе представляю поисковые боты не умеют производить xslt-трансформацию. Проиндексирует ли сайт поисковик? Что попадет в кеш поисковика?
+1
Holden #
Полностью делать сайт по такой схеме смысла нет. Поисковики не могут его нормально проиндексировать. Используйте только там где это необходимо.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.