将 query-declared 外部函数用于 XQuery
作为使用 API 将 Java™ 方法绑定到查询中函数的备用方法,可以直接在查询中声明 Java 外部函数。唯一需要的其他配置是在查询执行期间,将 Java 类绑定到类路径上。
过程
使用 java-extension XQuery 选项声明,您可以将前缀绑定到 Java 类。
declare option xltxe:java-extension "prefix = className";
注: 只要将任何前缀名称绑定到 http://www.ibm.com/xmlns/prod/xltxe-j 名称空间,即可将其用于 java-extension 元素。
将前缀绑定到 Java 类后,可以通过指定按逗号分隔的前缀和方法名称,调用绑定的类中的方法。
prefix:methodName(Params*)
示例
调用静态方法
准备 XQuery 源(使用 query-declared 外部函数)时,声明 Java 类绑定的前缀:
declare namespace calc="http://com.example/myApp/Calculator";
declare namespace sf="http://com.example/myApp/standardFormat";
declare namespace xltxe="http://www.ibm.com/xmlns/prod/xltxe-j";
declare option xltxe:java-extension "calc = org.company.Calculator";
declare option xltxe:java-extension "sf = org.standards.Formatter";
sf:format(calc:sqrt(64), "ISO-42.7")
假定在 xquerySource 源对象中此查询可用,以下代码用于准备查询:
// Create the factory
XFactory factory = XFactory.newInstance();
// Create an XQuery executable for the query
XQueryExecutable executable = factory.prepareXQuery(xquerySource);
以下代码执行示例中准备的查询:
// Create a result object to store the transformation result
Result result = new StreamResult(System.out);
// Execute the XSLT executable
XSequenceCursor xsc = executable.execute();
// Output the result
xsc.exportSequence(res);
提供的示例查询假定 org.company.Calculator 类包含采用一个参数的静态方法 sqrt(),org.standards.Formatter 类包含采用两个参数的静态方法 format()。准备时,类路径上不需要类;但执行查询期间需要类。
以下为 org.company.Calculator 和 org.standards.Formatter
类的示例实现:
package org.company;
public class Calculator {
public static int sqrt(int val) {
return (int)Math.sqrt(val);
}
package org.standards;
public class Formatter {
public static String format(int val, String pattern) {
return "Formatting " + val + " using pattern " + pattern;
}
}
调用实例方法
从类调用实例方法与调用静态方法稍微有些不同,不同之处体现在实例对象的需求方面。
为了从查询中的 Java 类获取实例对象,必须调用其新的构造函数:
prefix:new(Params*)
然后,您可以将结果存储在 XQuery 变量声明中,如以下查询所说明:
declare namespace car="http://com.example/myApp/car";
declare namespace xltxe="http://www.ibm.com/xmlns/prod/xltxe-j";
declare option xltxe:java-extension "car = org.automobile.Car";
declare variable $var := car:new(3);
car:getDoors($var)
假定在 xquerySource 源对象中此查询可用,以下代码用于准备查询。
// Create the factory
XFactory factory = XFactory.newInstance();
// Create an XQuery executable for the query
XQueryExecutable executable = factory.prepareXQuery(xquerySource);
以下代码执行示例中准备的查询:
// Create a result object to store the transformation result
Result result = new StreamResult(System.out);
// Execute the XSLT executable
XSequenceCursor xsc = executable.execute();
// Output the result
xsc.exportSequence(res);
此示例查询假定 org.automobile.Car 类包含采用类型 int 自变量的构造函数。此外,org.automobile.Car 类还包含未采用自变量的实例方法 getDoors()。从 query-declared 外部函数调用实例方法的语法需要将已创建实例对象作为第一个自变量传入。
以下是 org.automobile.Car 类的示例实现:
package org.automobile;
public class Car {
private int doors;
public Car (int doors) {
this.doors = doors;
}
public int getDoors() {
return doors;
}
}
还支持继承实例方法。
如果 org.automobile.Car 类具有子类 org.automobile.Sedan,那么可以创建 org.automobile.Sedan 类的实例,并将其用于调用 org.automobile.Car 中的方法。以下查询说明了此情况:
declare namespace car="http://com.example/myApp/car";
declare namespace sedan="http://com.example/myApp/sedan";
declare namespace xltxe="http://www.ibm.com/xmlns/prod/xltxe-j";
declare option xltxe:java-extension "car = org.automobile.Car";
declare option xltxe:java-extension "sedan = org.automobile.Sedan";
declare variable $var := sedan:new(5);
car:getDoors($var)
以下是 org.automobile.Sedan 的示例实现:
package org.automobile;
public class Sedan extends Car {
public Sedan (int doors) {
super(doors);
}
}
Limitation: 用于在 Java 类中解析方法的机制需要仅存在一种方法,且名称和元数匹配。如果存在多种方法,且名称相同而元数不同,那么会抛出错误。