Xpath 2.0, saxon и Grails: как это дело подружить

Xpath 2.0, saxon и Grails: как это дело подружить

Внимание! это очередная статья
из серии «для себя» — пишу, чтобы не забыть, как решал свои задачки

Столкнулся с задачей: подключить к Grails-приложению saxon (XSLT 2.0 и Xpath 2.0 процессор). Если в отношении XSLT никаких проблем не возникло, и все решилось через механизмы JAXP, то Xpath через JAXP подключаться не хотел. Делал все как указано в документации к saxon — без результата. Пока не залез в примеры кода из дистрибутива saxon.

Дело в том, что jaxp предполагает простое подключение различных библиотек для выполнения стандартных функций. К примеру, чтобы подключить в качестве XSLT процессора тот же saxon, достаточно задать соответствующее системное свойство:

System.setProperty ("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl")

и все в шоколаде, приложение способно обрабатывать XSLT2.0

Вроде бы та часть, что отвечает за Xpath должна делаться так же, стереотипно:

System.setProperty ("javax.xml.xpath.XPathFactory",
"net.sf.saxon.xpath.XPathFactoryImpl")

Ан нет, эта вещь не работает... Во всяком случае, в контексте контроллера Grails. вызов

this.xpfactory = XPathFactory.newInstance();
println this.xpfactory.class // -> com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl

- дает на выходе объект класса com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl из пакета rt.jar

не помогает даже прямое обращение к оригинальному классу:

this.xpfactory = net.sf.saxon.xpath.XPathFactoryImpl.newInstance();
println this.xpfactory.class // -> com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl

- результат тот же самый.

Уже думал бросить эксперименты с этим xpath2.0, но наткнулся на примеры кода, поставляемые с саксоном. Они то ведь как-то работают!

Оказывается, что работают, но нужно соблюсти два условия:

  1. Немножко не такое системное свойство задаем
  2. Используем в newInstance() указание на тип исходных xml c которыми работаем

System.setProperty ("javax.xml.xpath.XPathFactory:"+XPathConstants.DOM_OBJECT_MODEL, "net.sf.saxon.xpath.XPathFactoryImpl")
this.xpfactory = XPathFactory.newInstance(XPathConstants.DOM_OBJECT_MODEL);
println this.xpfactory.class // -> net.sf.saxon.xpath.XPathFactoryImpl

Я работаю с DOM, поэтому и указана XPathConstants.DOM_OBJECT_MODEL

Вот на такие нечеловеческие усилия приходится идти, чтобы пользоваться Grails, не имея опыта работы с Java :-)

Однако, результат получен. Теперь можно пользоваться милым сердцу XSLT из Grails, не прибегая к Grails views и всевозможным Tag library. Если исполнюсь пассионарной энергии, то оформлю то, что сделал в виде XSLT Grails plugin - вдруг да кому еще нужно будет...

Комментарии (0)

mem: 1161 total: 11 module: 5 xsl: 3