如何注册 Saxon/XSLT 扩展函数以便在 BaseX/XQuery 中访问它们(JAXP API)
How to register Saxon/XSLT extension functions such that they accessible in BaseX/XQuery (JAXP APIs)
我有几个 Saxon/XSLT 扩展函数,它们是通过 simple interface 创建的,我这样注册:
Processor proc = new Processor(false);
proc.registerExtensionFunction(myExtensionFunctionInstance);
现在我想将它与 BaseX 一起使用,但我看到 BaseX instantiates its own Processor instance through JAXP APIs:
// Somewhere inside basex's XSLT transformer instantiation (see link above).
final TransformerFactory tf = TransformerFactory.newInstance();
看来我需要找到一种方法来更改 BaseX 使用的工厂,以便我可以注册我的函数。
如果我做对了,我需要创建自己的工厂实现。改编自撒克逊人的 net.sf.saxon.TransformerFactoryImpl:
package my.package;
public class MyOwnTrasnformerFactory extends SaxonTransformerFactory {
public TransformerFactoryImpl() {
super();
ExtensionFunction myFunction = new MyExtFunction(...);
this.processor.registerExtensionFunction(myFunction);
}
public TransformerFactoryImpl(Configuration config) {
super(config);
ExtensionFunction myFunction = new MyExtFunction(...);
this.processor.registerExtensionFunction(myFunction);
}
}
然后我可以做:
System.setProperty(
"javax.xml.transform.TransformerFactory",
"my.package.MyOwnTrasnformerFactory");
- 这看起来是正确的方法吗?
- 是否有另一种方法可以在我的程序的生命周期内创建一个处理器实例,而无需创建我的自定义工厂?我正在使用 Clojure,creating Java classes (genclass) 不太方便,也不太动态。
我最终实施了我的问题中描述的解决方案...这是一个完整的要点:
https://gist.github.com/EmmanuelOga/018ece8b4776636ce1ab3f73e215ce75
相关部分:
(ns rainbowfish.xslt-factory
(:import [net.sf.saxon Configuration]
[net.sf.saxon.lib Feature])
(:gen-class
:name rainbowfish.XsltFactory
:extends net.sf.saxon.jaxp.SaxonTransformerFactory
:post-init configure))
(defn -configure
"Generated Java class will call this method right after
construction. Here we get a chance to grab Saxon's processor for
configuration purposes (for example, adding extension functions)."
[this & args]
(let [processor (.getProcessor this)]
;; Here we can do whatever we want to the processor,
;; For instance, register some extension functions.
(doto processor
(.registerExtensionFunction some-function))))
即使用clojure定义了Javaclassrainbowfish.XsltFactory
。由于使用了gen-class,所以需要通过调用compile('rainbowfish.xslt-factory)
或者让lein编译等方式编译
现在我们有一个配置 XSLT 处理器的 class,我们需要通知 BaseX 它应该使用它。 BaseX 为此读取 JAXP 配置。配置可以这样设置:
(System/setProperty
"javax.xml.transform.TransformerFactory",
"rainbowfish.XsltFactory")
...这应该在创建 BaseX 服务器实例之前调用。有关更多详细信息,请参阅要点!
我有几个 Saxon/XSLT 扩展函数,它们是通过 simple interface 创建的,我这样注册:
Processor proc = new Processor(false);
proc.registerExtensionFunction(myExtensionFunctionInstance);
现在我想将它与 BaseX 一起使用,但我看到 BaseX instantiates its own Processor instance through JAXP APIs:
// Somewhere inside basex's XSLT transformer instantiation (see link above).
final TransformerFactory tf = TransformerFactory.newInstance();
看来我需要找到一种方法来更改 BaseX 使用的工厂,以便我可以注册我的函数。
如果我做对了,我需要创建自己的工厂实现。改编自撒克逊人的 net.sf.saxon.TransformerFactoryImpl:
package my.package;
public class MyOwnTrasnformerFactory extends SaxonTransformerFactory {
public TransformerFactoryImpl() {
super();
ExtensionFunction myFunction = new MyExtFunction(...);
this.processor.registerExtensionFunction(myFunction);
}
public TransformerFactoryImpl(Configuration config) {
super(config);
ExtensionFunction myFunction = new MyExtFunction(...);
this.processor.registerExtensionFunction(myFunction);
}
}
然后我可以做:
System.setProperty(
"javax.xml.transform.TransformerFactory",
"my.package.MyOwnTrasnformerFactory");
- 这看起来是正确的方法吗?
- 是否有另一种方法可以在我的程序的生命周期内创建一个处理器实例,而无需创建我的自定义工厂?我正在使用 Clojure,creating Java classes (genclass) 不太方便,也不太动态。
我最终实施了我的问题中描述的解决方案...这是一个完整的要点:
https://gist.github.com/EmmanuelOga/018ece8b4776636ce1ab3f73e215ce75
相关部分:
(ns rainbowfish.xslt-factory
(:import [net.sf.saxon Configuration]
[net.sf.saxon.lib Feature])
(:gen-class
:name rainbowfish.XsltFactory
:extends net.sf.saxon.jaxp.SaxonTransformerFactory
:post-init configure))
(defn -configure
"Generated Java class will call this method right after
construction. Here we get a chance to grab Saxon's processor for
configuration purposes (for example, adding extension functions)."
[this & args]
(let [processor (.getProcessor this)]
;; Here we can do whatever we want to the processor,
;; For instance, register some extension functions.
(doto processor
(.registerExtensionFunction some-function))))
即使用clojure定义了Javaclassrainbowfish.XsltFactory
。由于使用了gen-class,所以需要通过调用compile('rainbowfish.xslt-factory)
或者让lein编译等方式编译
现在我们有一个配置 XSLT 处理器的 class,我们需要通知 BaseX 它应该使用它。 BaseX 为此读取 JAXP 配置。配置可以这样设置:
(System/setProperty
"javax.xml.transform.TransformerFactory",
"rainbowfish.XsltFactory")
...这应该在创建 BaseX 服务器实例之前调用。有关更多详细信息,请参阅要点!