Vote saxon что это
Tardis
Spoilers are precisely defined here. Rules vary by the story’s medium. Info from television stories can’t be added here until after the top or bottom of the hour, British time, closest to the end credits roll on BBC One. Therefore, fans in the Americas who are sensitive to spoilers should avoid Tardis on Sundays until they’ve seen the episode.
Vote Saxon
Vote Saxon was the ultimately successful campaign made by «Harold Saxon», actually the Master, to become Prime Minister of the United Kingdom in an election held in 2008.
History [ ]
Appearing on Earth just after the downfall of British Prime Minister Harriet Jones, which was brought about the Tenth Doctor on 25 December 2006, (TV: The Sound of Drums, The Christmas Invasion) the Master quickly infiltrated the British government by fabricating the identity of Harold Saxon. At the same time, the Archangel Network of fifteen satellites was launched by the Master, already a minister. Ostensibly a mobile phone network, Archangel was used by the Master to influence the human population of Earth, first to believe the story of «Harold Saxon», then to «Vote Saxon», as well as preventing the Doctor from sensing him as another Time Lord on Earth. However, the Master later conceded that only «99» or «98» percent of people were successfully influenced. (TV: The Sound of Drums, The Christmas Invasion)
After March 2007, Saxon was reported by The Daily Telegraph newspaper as leading polls with 64% during a state of «government paralysis». (TV: Love & Monsters) In light of the downfall of Harriet Jones, an election was called to decide the next Prime Minister. Harold Saxon put forward his bid for Prime Minister, beginning the «Vote Saxon» campaign, with posters appearing from London to Cardiff (TV: Smith and Jones, Captain Jack Harkness) while websites were established to cover Harold Saxon. Among the people who backed Saxon were Ann Widdecombe, Sharon Osbourne and the band McFly. (TV: The Sound of Drums)
Among those who were influenced by Archangel was Martha Jones, who had intended to vote for Saxon despite being ignorant of his policies and what he stood for. (TV: The Sound of Drums)
On election day, (TV: 42) as the vote «[swang]» Saxon’s way, future members of his cabinet, as the Master put it, abandoned their political parties and jumped on «the Saxon bandwagon». (TV: The Sound of Drums)
Ultimately, the Master won the election as «Harold Saxon», which led to the Toclafane invasion. (TV: The Sound of Drums)
Xalan, Saxon и 8 ферзей
Сегодня я хочу рассказать об XSLT. Этот, весьма своеобразный, язык может оказаться очень полезным в тех случаях, когда требуется обработать XML-данные, сколь нибудь не тривиальным образом. Я расскажу о двух наиболее популярных (в среде Java-разработчиков) реализациях XSLT-процессора, подробно остановлюсь на вопросах их использования из Java-кода и попытаюсь сравнить их производительность. В качестве теста для сравнения производительности, я буду использовать широко известную задачу о расстановке 8-ми ферзей на шахматной доске.
Поскольку решение подобных задач, с использованием XSLT вряд ли можно отнести к категории нормальной деятельности, топик помещен в соответствующий раздел. В то же время, я надеюсь, что эта статья будет полезна, в качестве учебного материала.
Xalan vs Saxon
Несмотря на достаточно большое количество существующих реализаций XSLT, в случае, если мы говорим о разработке на языке Java, выбор (на мой взгляд) сводиться к двум упомянутым в заголовке. Действительно, использование реализации от Microsoft, затруднено тем, что она поставляется в виде нейтивной dll, а реализация от Oracle предназначена для использования непосредственно в базе данных. Другие реализации гораздо менее известны (меня действительно интересует этот вопрос и я буду рад дополнительно рассмотреть любую из Java-совместимых реализаций XSLT, предложенную участниками Хабра).
Saxon, на мой взгляд, является наиболее развитым, на сегодняшний день, XSLT-процессором. Матрица предоставляемых им возможностей действительно впечатляет. Хотя наиболее интересные из этих возможностей поддерживаются только коммерческими дистрибутивами, поставляемый по условиям Mozilla Public License version 1.0 Saxon HE также предоставляет полноценную поддержку XPath и XSLT как версии 1.0, так и версии 2.0. Для того, чтобы понять, насколько поддержка XSLT 2.0 может облегчить жизнь, достаточно бегло ознакомиться с содержанием популярного учебника XSLT Cookbook за авторством Sal Mangano.
Главным достоинством Xalan, в отличии от Saxon, является использование менее ограничивающей Apache License Version 1.1. Эта реализация обеспечивает полноценную поддержку XSLT версии 1.0. Еще одним козырем, как Xalan так и Saxon, является заявленная ими полная поддержка промышленного стандарта TrAX. О том, что это такое и для чего оно нужно, я расскажу в следующем разделе.
Именем TrAX-а и JAXP-а его
TrAX — это API для выполнения XML-преобразований, разработанное рядом заинтересованных организаций с целью унификации взаимодействия с XSLT-процессорами. В части относящейся к Java API он был опубликован Sun как JAXP 6 февраля 2001 года. Для ознакомления с возможностями использования JAXP я рекомендую прочитать следующие статьи.
Коротко говоря, JAXP позволяет работать с XML-документами в Java, используя как DOM, так и SAX (в том числе, реализуя XSLT-преобразования), не привязывая код к используемой реализации и версии обработчика. Для корректной работы достаточно обеспечить присутствие используемого jar-а в classpath и установить соответствующее System Property (последнее не обязательно если нет разницы какой из обработчиков упомянутых в classpath использовать).
Посмотрим, как это выглядит на практике. Для начала, попробуем загрузить XML-файл в память и получить из него некоторое значение, используя выражение XPath.
XML-файл будет выглядеть следующим образом:
Здесь не так много данных, но начинать надо всегда с простого (в дальнейшем, мы будем использовать это значение для задания размера шахматной доски).
Здесь мы получаем итератор по простому XPath-запросу, проходим по набору узлов (состоящему из одного узла) и выводим его значение (если это текстовый узел) или текстовое содержимое (в случае использованного запроса всегда будет работать этот вариант). Как мы видим, все совсем не сложно, но если мы достаем скалярное значение, можно поступить еще проще:
Иногда (особенно при обработке XML-файлов большого объема) использования DOM стараются избегать (поскольку данные требуется целиком загружать в память). В таких случаях, для разбора XML применяют SAX. JAXP позволяет преобразовать один формат в другой (например SAX в DOM) используя следующую трансформацию (если при выполнении трансформации не указана таблица стилей, выполняется тождественное преобразование, что зачастую бывает весьма удобно):
Понятно, что таким образом мы не избавимся от загрузки XML-файла в оперативную память, поскольку для промежуточного хранения мы все равно используем DOM. Как мы можем обрабатывать большие файлы? Например, мы можем получить SAX-поток при разборе большого XML-файла и преобразовать его таким образом, чтобы в память загружался не один большой, а множество мелких файлов поочередно. Попробуем сформировать SAX-события вручную:
Как мы видим, здесь также нет ничего сложного. Хочу лишь предостеречь от возможной передачи в параметр uri вызовов startElement и endElement null-значений. Для Xalan это работает нормально, но Saxon выбрасывает NullPointerException.
Для полноты картины, осталось добавить, что преобразования можно связывать в цепочки, образуя конвейер. На выходе, результат можно сохранять, например, в файл:
Пока, мы видим здесь три пустых обработчика, выполняющих тождественное преобразование. В следующем разделе мы начнем наполнять их XSLT-кодом.
Первый подход к снаряду
Итак, нам надо расставить ферзей на шахматной доске таким образом, чтобы они не били друг-друга. Для начала нам требуется сгенерировать список позиций, удовлетворяющих условию задачи. Определимся с кодированием позиций. Поскольку, по условиям задачи, фигуры не могут располагаться на одной вертикали, мы можем использовать строку десятичных цифр для кодирования корректных позиций.
Позиция цифры будет означать номер вертикали, а само значение — номер горизонтали, на которой расположена фигура. Поскольку мы используем десятичные цифры, начиная с единицы, мы сможем решать задачу для квадратной доски размером от 1×1 до 9×9 клеток. Чтобы расчеты выполнялись быстрее, рекомендую установить размер меньше 8-ми (5×5 клеток будет в самый раз). Код на XSLT (несмотря на свою излишнюю многословность) вполне понятный:
Здесь мы используем упрощенную проверку на взаимный бой фигур, не выполняя проверку боя по диагонали. Запустив следующую программу на выполнение:
… можно получить список возможных решений задачи «8 ладей».
Чтобы исключить возможные обвинения в подмене условий задачи, усложним проверку взаимного боя фигур. Для упрощения повторного использования кода, XSLT предлагает использовать возможность импорта. Ей мы и воспользуемся:
Замечу, что здесь необходимо использовать именно инструкцию import, а не инструкцию include, чтобы обеспечить более высокий приоритет шаблонов в импортирующей таблице по сравнению с импортируемой (это очень похоже на наследование).
Чтобы весь этот импорт заработал, необходимо внести еще одно небольшое изменение в Java-код. Определим URIResolver, который будет вызываться при запросе URI в процессе разбора XSLT:
… и передадим его фабрике:
Конечно, в нашем случае, когда все xsl-файлы загружаются из одного дискового каталога, XSLT-процессор и сам прекрасно разберется в том откуда подгрузить файл, но представьте себе, например, что XSLT-код загружается из LOB-поля в базе данных!
Запустив программу на выполнение, мы получим список решений задачи.
Что нам с ним делать?
Список решений в том виде, в котором мы его составили, не очень удобен для человека. Он компактен, но не дает наглядного представления о позициях (без некоторого мысленного усилия). Считать количество решений вручную, используя его, также не слишком удобно. К счастью, обработка таких данных — это именно то, для чего предназначен XSLT. Добавив в конец цепочки трансформаций вызов еще одного обработчика, мы сможем легко подсчитать количество решений:
… либо, показать их в наглядной форме:
В этом примере следует обратить внимание на нестандартное расширение Xalan redirect:write, позволяющее перенаправить вывод в другой файл (в XSLT 2.0, для этих целей, добавлена стандартная инструкция). К сожалению, мне не удалось перенаправить результат такого redirect-а в произвольный SAX-поток, что, на мой взгляд, несколько снижает его ценность.
Магия отражений
Мы получили решения, но их как-то слишком много. Это потому, что мы не отсеиваем повторы с учетом возможных поворотов и отражений доски. Давайте получим список уникальных решений?
Если немного подумать, становиться понятно, что всевозможных поворотов и отражений доски всего 8 (учитывая первоначальный вариант). Реализуем вспомогательные шаблоны для отражения позиции (в нашем внутреннем представлении) по вертикали (flip), горизонтали (reverse) и поворота доски на 90 градусов (rotate):
Здесь использованы реализации функций reverse и index-of из замечательной книги Сэл Мангано «XSLT Сборник рецептов». Сама фильтрация уникальных значений — классическая задача на использование оси preceding-sibling:
К сожалению, в XSLT 1.0, мы не можем решить эту задачу одним XPath выражением, но в XSLT 2.0 добавлена возможность «обертывания» шаблонов в пользовательские функции.
На этом все! Мы решили задачу.
Кто быстрее?
Измерения будем проводить при помощи следующего кода:
Заменяя константу SAXON_TRANSFORM_FACTORY на XALAN_TRANSFORM_FACTORY можно переключаться с одного XSLT-процессора на другой.
К сожалению (по непонятной мне причине) мне не удалось заставить нормально работать ни одну из версий ветки Saxon-HE. Код работает, но каждый вызов отрабатывает невероятно медленно. Например вызов TransformerFactory.newInstance() отрабатывал несколько минут! При этом один из CPU утилизировался полностью, а код (судя по отладчику) большую часть времени находился где-то в районе реализации SHA-2.
К счастью, более ранняя версия из соседней ветки работает нормально. Вот итоговые картинки:
Можно заметить, что, в этой задаче, оба XSLT-процессора работают приблизительно с одинаковой скоростью. Таким образом, использование Saxon может быть оправдано только при использовании функциональности XSLT 2.0 или XSLT 3.0.
Все исходные тексты, как обычно, выложены на GitHub.
Напоследок, хочу поблагодарить jonic за помощь оказанную им при подготовке статьи.