• 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 скрипт, отдавая результат трассировки со своего домена.

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

    Метки: , , ,
  • 15 комментариев

    1. Alexey
      4 октября 2010

      Прикольно. А где это реально нужно? ну т.е. где этот инструмент нужен настока чтобы его скачали себе разработчики и использовали.
      планируется ли ввести поддержку xslt2?

    2. Сергей Чикуенок
      4 октября 2010

      Нужен, в первую очередь, для дебага. Очень часто нужно узнать, откуда именно выводится фрагмент html-кода, чтобы внести нужные правки.

      По поводу xslt2 — вполне возможно. Насколько я знаю, его поддерживает только Saxon, соответственно, нужно будет только портировать трейсер с Saxon 6 на 9.

    3. 4 октября 2010

      Поддержу Алексея и хочу узнать какой смысл от xslt в сайтах (а тут он из джсона ещё генерится) кроме дополнительной нагрузки на генерацию html, на парсинг xml, xslt?

      И да, возникает вопрос, вы реально делаете веб-проекты на Java? Какие нагрузки они создают?

    4. Сергей Чикуенок
      4 октября 2010

      XSLT — это шаблонизатор. Он может использоваться как на клиенте, так и на сервере. То, что я тут описал (генерация из JSON и так далее) — это всего лишь описание работы трэйсера, а не самого пробразования.

      И я считаю XSL лучшим шаблонизатором из тех, что существуют.

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

    5. Aleksey
      5 октября 2010

      Сергей, в докладе на яндекс.субботнике был доклад о шаблонизации на клиенте.
      Там как раз было рассмотрено сравнение XSLT и JS шаблонизации. В противовес скорости работы XSLT всегда ставилось убогость его использования, т.е. недостаточность методов для обработки шаблонов.

      А как Вы считаете?

    6. Сергей Чикуенок
      5 октября 2010

      Никогда не считал функционал XSL убогим. XSL + EXSLT решают 99,9% всех моих задач. Да, согласен, что синтаксис XSL не всем сразу понятен и некоторые вещи вроде цикла с заданным количеством итераций делаются через жопу, но, тем не менее, делаются. То есть большинство криков о том, что в XSL что-то сделать невозможно как раз связано с тем, что люди не умеют им пользоваться.

    7. Aleksey
      5 октября 2010

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

    8. 5 октября 2010

      Странно, что для libxsl чего-то подобного нет. Или я плохо искал?

    9. Alexey
      5 октября 2010

      Я активно использую как шабонизатор twig (идея заимствована в django), так и XSL. И тем и другим активно пользуюсь более полугода. Обычные шаблонизаторы куда проще, с ними быстрее сделать задачу, где в XML нужно писать много кода. Но я ненавижу этим заниматься тупые вставки кода пхп в html. А на XSL можно сказать что я программирую) код писать сложнее) Очень нравится красивость что данные и обработка их в разных местах, нужно писать выборки.
      XSL — это круто, и есть задачи где он может очень пригодиться(трансформация на клиенте, когда не хочется быть зависимым от серверного языка), но это долгий путь и не для всех) Большинство счастливо что использует заточенные под наполнение данными шаблонизаторы.
      xslt2 мог бы исправить ситуацию, но хреново его поддерживают… Походу всем и так неплохо..

    10. Ви
      6 октября 2010

      В шаблоне из примера (simple.xsl) используются сущности &root;, &super_item;, но откуда они берутся нифига не понятно 🙂

    11. Сергей Чикуенок
      6 октября 2010

      Сергеев Виталий, тут нужна поддержка трассировки со стороны самого трансформатора. Насколько я знаю, это есть только у Saxon.

      Ви, сущности берутся из подключаемого DTD-файла, просто я вырезаю ссылки на DTD, чтобы локальный xml-парсинг работал нормально

    12. 6 октября 2010

      Очень классно!:))

    13. nex2hex
      6 октября 2010

      Для отладки xslt могут пригодиться еще эти инструменты:
      http://www.altova.com/xmlspy/xslt-debugger.html

    14. 8 октября 2010

      Последняя бесплатная версия Saxon/java с поддержкой EXSLT — это saxonb9-1-0-8. В более новых версиях EXSLT отрезан.

    15. Ruslan
      18 октября 2010

      Привет,
      не уверен что скажу что то умное, но помоему с твоей задачей справится функция: saxon:path
      Привет из Амстердама )))