Посты с тэгом «xsl»

  • XSL Tracer

    Я, наконец-то, более-менее довёл до ума свой новый проект, которым хочу поделиться с народом.

    Проект называется XSL Tracer. Его задача заключается в том, чтобы ответить на простой вопрос: откуда после XSL-трансформации пришёл тот или иной элемент? Как это работает можно увидеть на демо-странице. Там отображается результат XSL-преобразования — обычный HTML-документ. Кликнув по любому элементу можно получить подробную информацию о нём:

    • XSL: шаблон, где выводится элемент.
    • Context: контекстный XML (на который сработал матч, в случае xsl:apply-templates). Сам элемент выводится урезанным (только 10 внутренних тэгов), чтобы в случае, если это будет корневой элемент, браузер не умер в муках (да и толку от полной структуры никакого).
    • Source: место в шаблоне, где непосредственно генерируется выбранный элемент. Очень удобно в случае, если делаете сopy-of результатирующей структуры (в примере это html-код, заданный внтутри переменной).
    • Call stack: стэк вызовов apply-template/call-template/apply-imports, через который дошли до вызова текущего шаблона
    • Inner calls: список внутренних вызовов шаблонов, которые по каким-то причинам нельзя отобразить (по крайней мере пока) в документе. Например, вызов шаблонов, выдающих атрибуты для выбранного элемента, или его текстовое содержимое. Список отображается под Call stack, и только в том случае, если такие вызовы есть.

    Демка нормально работает в Safari/Firefox/Chrome, Opera жутко тормозит на больших документах, а в IE даже не открывал.

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

    Как это работает

    Проект состоит из двух частей: бэкэнд и фронтэнд.

    На бэкэнде используется Saxon 6.5 (пока эта версия, так как в 9.2 лично у меня вылезло куча проблем с EXSLT). У него есть встроенный механизм трассировки, который по умолчанию генерирует результат в виде XML (такой файл на реальных проектах вырастает до нескольких мегабайт). Я написал свой трассировочный класс, который выводит данные в более компактном и лёгком JSON-формате, а также дополнительные данные вроде списка используемых в трансформации XSL и XML (подключённых через document()) документов. А также он делает дополнительные штуки вроде резолвинга result-tree фрагментов при вызове xsl:copy-of.

    Этот трассировщик генерирует JSON-документ и результатирующий документ (то есть результат предобразования) и собирает их в одном HTML-файле, который можно открывать в браузере.

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

    Как запускать

    1. Должна быть установлена Java (версия особо не важна).
    2. Скачиваем Saxon 6.5
    3. Скачиваем трэйсер
    4. Генерируем трассировку вот такой командой в консоли:

    java -classpath /path/to/tracer.jar:/path/to/saxon.jar ru.imobilco.XSLTracer -to /path/to/trace-result.html /path/to/input.xml /path/to/template.xsl

    В случае успешной работы трэйсера сгенерируется файл trace-result.html, который можно сразу открывать в браузере (CSS и JS берутся с моего сервера). Если возникла ошибка во время трансформа, то файл будет сгенерирован, но вместо документа увидите нормальное сообщение об ошибке. В случае ошибки работы Java, увидите сообщение в консоли.

    Надо помнить, что Saxon очень чувствителен ко всяким всяким отхождениям от спецификации, поэтому то, что работало в Xalan/libxsl/где-то ещё может не сработать в Saxon. Но исправления, как правило, довольно мелкие и незначительные.

    Онлайн-версия

    Мой коллега Лёха Баранов написал сервлет, который позволяет запускать через веб, передавая ссылки на XML и XSL файлы. Для него был заведён специальный проект xmltools.ru. Работает просто: указываете ссылки на файлы и, если нужно, данные для http-авторизации. Далее сам трансформ находит все зависимые файлы, скачивает их и делает трансформ.

    Но с онлайн-версией не так всё просто. В частности, когда результат отдаётся фронтэнду, он тоже начинает скачивать внешние файлы через аякс. И, как вы уже, наверно, догадались, включается ограничение Same-Origin Policy, которое не позволяет загружать данные с другого домена. Вариантов решения два: либо вы свой сервер настраиваете на cross-domain ajax, либо используете xmltools.ru как сервис, запрашивая трансформ через какой-нибудь php/python/ruby скрипт, отдавая результат трассировки со своего домена.

    Онлайн-версия пока находится в состоянии «альфа», поэтому может быть много багов. И пока бесплатна. Подчёркиваю, пока бесплатна. Дело в том, что такие трассировки генерируют очень большую нагрузку, и если она возрастёт до каких-то критических значений, то придётся прикрыть лавочку и предоставлять услугу на коммерческой основе.

    Метки: , , ,
  • Zen Coding для textarea

    Представляю первую бета-версию плагина, который позволяет использовать мощь Zen Coding у себя на сайте без всяких плясок с бубном: Zen Coding for <textarea>. Название говорит само за себя: ZC работает прямо в <textarea>. Для работы достаточно подключить всего один JS-файл к себе на сайт.

    Как это работает

    Плагин использует технику под названием event delegation: вешаются события по отлову нажатий клавиш на родительский документ; когда пользователь пытается вызвать какую-нибудь команду (например, Expand Abbreviation), плагин проверяет, какой элемент является источником. Если это <textarea> — отрабатываем команду, если нет — просто пропускаем событие. Таким образом, никакой дополнительной настройки для работы плагина не требуется: подключаем файл и радуемся жизни.

    Испытать плагин можно прямо на это странице в форме добавления комментария. Чтобы узнать допустимые сочетания клавиш достаточно кликнуть на иконке «Powered by Zen Coding» рядом с полем ввода.

    Плюшки

    Помимо основных возможностей Zen Coding плагин позволяет сделать написание кода в <textarea> гораздо более приятным занятием. Во-первых, можно задействовать клавишу Tab для разворачивания аббревиатур. Если аббревиатуру не получается развернуть, то добавляется символ табуляции (то есть просто делается отступ, как в обычных редакторах). Во-вторых, можно включить форматирование кода при добавлении переводов строк (нажатие на Enter). Новая строка будет добавлена вместе с отступом предыдущей строки, а если каретка находилась как раз между открывающим и закрывающим тэгом — будет добавлено дополнительное форматирование.

    По умолчанию эти опции отключены, их можно включить одним из доступных способов.

    Настройка

    У плагина есть ряд базовых настроек, которые можно в любой момент перекрыть. Все эти настройки записаны в переменной default_options файла manager.js:

    • profile — профиль форматирования результата разворачивания аббревиатур. По умолчанию применяется 'xhtml', доступны также 'plain', 'html', 'xml'.
    • syntax — синтаксис языка, с которым работаем в поле. По умолчанию это 'html', доступно также 'css', 'xml', 'xsl'. Можно создавать свой синтаксис (см. zen_settings.js).
    • use_tab – использовать клавишу Tab для разворачивания аббревиатур/добавления отступов.
    • pretty_break — включить форматирование переноса строк.

    Изменить настройки можно как глобально (применяются ко всем полям ввода), так и локально (применяются к конкретному полю).

    Для глобального изменения настроек нужно вызвать функцию zen_textarea.setup(), передав ей параметры, которые нужно изменить. Например, для того, чтобы глобально включить использование клавиши Tab и форматирование переносов строк, нужно вызвать такой код:

    	zen_textarea.setup({
    		use_tab: true,
    		pretty_break: true
    	});
    

    Для того, чтобы указать локальные настройки для конкретного поля достаточно указать ему класс вида zc-{название параметра}-{значение}. Например, для того, чтобы указать, что в данном поле нужно использовать синтаксис XSL, а также включить форматирование переносов строк, пишем вот такие классы:

    	<textarea class="zc-syntax-xsl zc-pretty_break-true"></textarea>
    

    Также можно переназначить сочетания клавиш на более привычные, для этого есть методы zen_textarea.shortcut(keystroke, action_name) и zen_textarea.unbindShortcut(keystroke). В качестве аргумента keystroke отдаем текстовое описание сочетания клавиш, например Shift+Alt+D, в качестве аргумента action_name — название действия, которое нужно выполнить.

    Для создания шорткатов можно использовать клавишу Meta: на Маке это будет означать Command, на PC — Ctrl. Полный список доступных действий и их шорткаты:

    addShortcut('Meta+E', 'Expand Abbreviation');
    addShortcut('Tab', 'Expand Abbreviation');
    addShortcut('Meta+D', 'Balance Tag Outward');
    addShortcut('Shift+Meta+D', 'Balance Tag inward');
    addShortcut('Shift+Meta+A', 'Wrap with Abbreviation');
    addShortcut('Ctrl+Alt+RIGHT', 'Next Edit Point');
    addShortcut('Ctrl+Alt+LEFT', 'Previous Edit Point');
    addShortcut('Meta+L', 'Select Line');
    addShortcut('Enter', 'Format Line Break');
    
    Метки: , , , ,
  • Подключение entity в XSL-шаблон

    Я очень люблю использовать XSL в качестве шаблонизатора — более гибкого механизма для вывода HTML/XML не придумаешь. А еще я использую Eclipse в качестве основной среды разработки: хоть он тяжелый и глючный, собака, но он единственный удовлетворяет большинство моих потребностей (никуда не перелезу, пока там не появится аналог PyDev и Mylyn).

    Шаблоны, которые я использую, построены на кастомных энтити. Так как XSL-переменные нельзя использовать в атрибуте match шаблона, это довольно удобный способ их эмулировать:

    <!ENTITY navigation "/document/system/navigation[@type = 'root']">
    ...
    <xsl:template match="&navigation;">
    	<ul id="nav">
    		...
    	</ul>
    </xsl:template>
    

    Все энтити хранятся в отдельном файле (entities.dtd), которые я подключаю вот так:

    
    <!DOCTYPE xsl:stylesheet SYSTEM "entities.dtd">
    
    <xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	...
    </xsl:stylesheet>
    

    В «штатном» Eclipse XSL editor это приводит к тому, что перестает code complete по XSL-тэгам — это баг всего Web Tools Project, связанный с тем, что при одновременном использовании XML Schema и внешнего файла с энтити предпочтение по code complete отдается последнему. Поиск решения этой проблемы привел меня к довольно интересному открытию. Теперь энтити я подключаю вот так:

    <!DOCTYPE xsl:stylesheet [
    	<!ENTITY % core SYSTEM "entities.dtd">
    	%core;
    ]>
    

    Это не только восстанавливает работу code complete, но и добавляет следующее преимущество: можно создавать локальные энтити в каждом файле и матчить на них шаблоны:

    <!DOCTYPE xsl:stylesheet [
    	<!ENTITY % core SYSTEM "entities.dtd">
    	%core;
    	<!ENTITY my_entity "/path/to/element[@with = 'very complex expression']">
    ]>
    ...
    <xsl:template match="&my_entity;">
    	сделать что-нибудь
    </xsl:template>
    
    <xsl:template match="&my_entity;[@some_attr = 'true']">
    	сделать что-нибудь другое
    </xsl:template>
    
    Метки: , ,