Как выполнить XSLT 2.0 с муравьем?
Я пытаюсь запустить XSLT-преобразование из файла ant.
Я использую таблицу стилей XSLT 2.0 с парсером Saxon 9 (с поддержкой XSLT 2.0).
Проблема в том, что кажется, что ant всегда вызывает парсер XSLT 1.0.
Вот мой файл муравья:
<xslt style="stylesheet.xslt"
basedir="core/"
extension=".xml"
destdir="core/"
classpath="D:\\DevTools\\saxon\\bin\\saxon9.jar">
</xslt>
Если я назову это напрямую (без муравья), это работает.
Любая идея?
6 ответов
Проблема в том, что, хотя Saxon добавляется в путь к классам, механизм JAXP по умолчанию определяет, какой TransformerFactory используется, и он будет использовать по умолчанию Xalan. Вам либо нужно:
- Задавать
javax.xml.transform.TransformerFactory
системная переменнаяnet.sf.saxon.TransformerFactoryImpl
, - Добавьте saxon9.jar к
CLASSPATH
системная переменная, или - использование
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
внутриxslt
элемент
Если у вас возникла эта проблема, убедитесь, что вы не используете Ant 1.8.1, потому что в Ant 1.8.1 есть ошибка, которая мешает этому работать. (Хотя это не проблема в оригинальном посте, потому что это было до выхода Ant 1.8.1).
Ваши варианты:
- Используйте версию Ant, в которой нет ошибки (например, Ant 1.7.1).
- Явно укажите saxon9.jar в
CLASSPATH
Ant до его запуска, либо:- Настройка системы
CLASSPATH
переменная среды, или - Использовать
-lib
опция командной строки дляant
- Настройка системы
- Определите свою собственную задачу, используя SAXON Ant (как описано в другом ответе в этой теме).
- Обходной путь, добавив
processor="org.apache.tools.ant.taskdefs.optional.TraXLiaison"
в качестве атрибутаxslt
элемент задачи.
Я бы предложил использовать вариант 1, а затем вариант 4.
Вариант 2 будет работать, но он возлагает ответственность на человека, который запускает ant, чтобы настроить свою среду и запустить ant должным образом. Я предполагаю, что вы не хотите этого, поэтому вы пытаетесь получить classpath
атрибут на xslt
задача на работу.
Вариант 3 имеет ограничения, потому что SAXON Ant требует загрузки и установки JAR-файла. Также SAXON Ant не работает с SAXON 9.2 или новее (а SAXON Ant не обновлялся с момента его создания в июне 2008 года).
В теории, указав factory
подэлемент делает процессор XSLT, который вы хотите использовать, явным образом - чтобы предотвратить загрузчик классов от поиска другого процессора XSLT ранее в своем поиске и использования его вместо вашего процессора XSLT, который находится ниже в CLASSPATH. На практике (по крайней мере, в муравье 1.7.0, 1.7.1 и 1.8.0), если factory
субэлемент указан xslt
задача игнорирует classpath
Атрибут - это означает, что вы должны явно указать CLASSPATH (вариант 2). Так что это не поможет решить исходную проблему. Однако это, похоже, исправлено в исходном коде Ant, поэтому может работать в выпусках после 1.8.1.
Этот учебник, кажется, дает пошаговые инструкции о том, как сделать то, что вы просите:
http://www.abbeyworkshop.com/howto/xslt/ant-saxon/index.html
Отсюда видно, что вы делаете правильные вещи. Вы уверены, что вам нужны двойные косые черты?
Обновление: в документации Ant xslt упоминается свойство factory, которое может помочь вам приблизиться:
РЕДАКТИРОВАТЬ: Michael Kay отметил, что AntTransform больше не поддерживается и не рекомендуется.
Создайте taskdef из класса Saxon AntTransform:
<taskdef name="saxon-xslt" classname="net.sf.saxon.ant.AntTransform" classpath="${basedir}/lib/saxon/saxon9.jar;${basedir}/lib/saxon/saxon9-ant.jar"/>
<saxon-xslt
in="${source.xml}"
out="${out.dir}/${output.xml}"
style="${basedir}/${stylesheet.xsl}"
force="true">
</saxon-xslt>
Я начал использовать стандарт <xslt>
задание с саксонской флягой, указанной в <classpath>
, но столкнулся с проблемами производительности. Казалось, что "завис" на некоторое время, когда задача была вызвана. Я обнаружил, что добавление processor="trax"
и указав <factory name="net.sf.saxon.TransformerFactoryImpl"/>
помогает ему работать намного быстрее
<xslt in="${source.xml}"
out="${out.dir}/${output.xml}"
style="${basedir}/${stylesheet.xsl}"
processor="trax">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
<classpath refid="saxon-classpath" />
</xslt>
Вместо того, чтобы ждать, пока это будет исправлено в 1.8.2, а затем ждать, пока все в конечном итоге обновятся до 1.8.2, вы можете запустить свой собственный макрос XSLT (для ситуаций, когда вы явно хотите использовать Saxon, а не выбранный пользователем механизм XSLT).)
<macrodef name="xslt" uri="com.mycompany.mydepartment">
<attribute name="in" />
<attribute name="out" />
<attribute name="style" />
<attribute name="classpath" default="${saxon.jar.path}" />
<attribute name="taskname" default="mydep:xslt" />
<element name="params" optional="true" implicit="true" />
<sequential>
<java classname="net.sf.saxon.Transform"
classpath="@{classpath}"
taskname="@{taskname}">
<classpath path="${saxon.jar.path}" />
<arg value="-s:@{in}" />
<arg value="-xsl:@{style}" />
<arg value="-o:@{out}" />
<params />
</java>
</sequential>
</macrodef>
затем вы можете вызвать его следующим образом (при условии, что для элемента проекта установлено xmlns:mydep="com.mycompany.mydepartment")
<mydep:xslt in="${myinput}"
out="${myoutput}"
style="${myxslt}">
<arg value="param1=value1" />
<arg value="param2=value2" />
<arg value="+param3=somefile.xml" />
</mydep:xslt>
Вы можете найти документы для передачи параметров в Saxon по адресу http://www.saxonica.com/documentation/using-xsl/commandline.xml
По крайней мере, в ant 1.8.0 задача xslt с указанным путем к классу очень медленная. Кажется, проблема в загрузке classpath. Я запустил ant в JDB, и он потратил все дополнительное время на чтение zip-файлов org.apache.tools.ant.AntClassLoader.loadClass.
Я пробовал это перед запуском и пошло намного быстрее:
ant -lib /path/to/saxon/saxon9.jar
Макродеф Тома Ховарда работает лучше, и хотя он имеет странный синтаксис для параметров XSLT, по крайней мере, это возможно.