среда, января 16, 2008

Подводные грабли XSLT

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

Тут я приведу основные грабли на которые я напоролся и способы их обхода.

1. в мозилле не работает xsl:disable-output-escaping, то есть нельзя трансформировать текст в xml, что в некоторых случаях весьма удобно. в противоположность этому xslt не поддерживает сериализацию в текст, что тоже было бы удобно. в обоих случаях приходится либо на сервере нужным образом подготавливать данные, либо писать нетривиальные шаблоны для трансформации.

2. в ие нельзя указывать xsl:method="xml" ибо тогда к выходному xml-лю будет дописан xml-декларация (да, omit-xml-declaration он игнорирует ), что приводит к переводу ие в режим совместимости с древними глючными версиями. то есть метод должен быть только "html"

3. однако, если указать xsl:method="html", то в опере перестают работать формы o_0. точнее, они работают, но не посылают ни одного поля. исследования показали, поля ввода по неизвестной причине просто не привязываются к форме. причина оказалась в web forms 2.0:
Setting an element's form attribute to the empty string (or to a string consisting only of IDs that do not correctly identify form elements) just disassociates the form control from its form, leaving it unassociated with any form.
и опера, как на зло, воспринимает неустановленный атрибут "form" как установленный в значение "пустая строка". вывод - нужно задать форме идентификатор, а всем полям - атрибут form с тем же значением. уже второй раз напарываюсь на этот кривой html5.0 (слоган которого - "обратная совместимость - наше всё") и его не менее кривую реализацию в опере (-_-)

4. xsl:fallback не поддерживает ни один браузер, хотя его-то нужно было бы реализовать в первую очередь! Впрочем, внутри шаблонов можно по старинке фильтровать браузеры.

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

upd: ко мне тут пришла гениально простая мысль ^_^ можно использовать method="xml", а ие переводить в режим соответствия стандартам простеньким скриптом:
window.onload= function(){
var html= document.documentElement.outerHTML;
if( html && ( document.compatMode == 'BackCompat' ) )
document.write( '<!DOCTYPE html>\n' + html );
}

6 комментариев:

Unknown комментирует...

Спасиб. Весьма интересна.

Анонимный комментирует...

может йа темный, а что мешает трансформировать шаблон в html на сервере?=)

Dark-Demon комментирует...

некошэрно ^_^
а если серьёзно, то пересылая только данные мы минимизируем размер страницы, а значит ускоряем её загрузку.
кроме того, при изменении оформления не потребуется инвалидировать весь кэш (как проксей, так и браузеров), а значит не будет резкого скачка запросов с бэкэндам и не будет ситуации, когда часть страниц уже в новом дизайне, а часть ещё в старом, ибо закэшировалось.

Dark-Demon комментирует...

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

Анонимный комментирует...

есть пара сомнительных моментов:
1. а как совместимость, не нужно будет тонну хаков городить для разных браузеров?
2. а "дикие" браузеры, которые даже скрипты не поддерживают и CSS, не говоря уж о XSLT (lynx, elinks)?

хотя преимущества есть, надо же тратить куда то 95% неиспользуемых ресурсов компутеров пользователей, экономя этим самым серверные ресурсы

Dark-Demon комментирует...

1. конечно нужно, как и везде ;-)
2. для диких браузеров и поисковиков нужно проводить трансформацию на сервере.