Although the usual way to invoke XQuery from a Java application is to compile and execute a query
as described above, it is also possible to invoke individual XQuery functions directly from Java if required.
This interface is very efficient but performs less validation of parameters than the standard interface described above.
To achieve this, first compile the query as described above, specifying a query that includes one or more
declare function declarations in the query prolog. It is then possible to retrieve the
UserFunction objects representing the compiled code of these functions, by calling the
getUserDefinedFunction method on the StaticQueryContext object.
As discussed above, the information is not held in the original StaticQueryContext object
(which Saxon does not alter), but in a modified copy which is obtainable from the XQueryExpression
object. Once found,
such a function can be called using its call method. The first argument to this is an array
containing the values of the arguments. These must be supplied using Saxon's native classes, for example
an integer argument is supplied as an instance of net.sf.saxon.value.IntegerValue. These
values must be of the type expected by the function; no conversion or type checking takes place (which
means that a ClassCastException will probably occur if the wrong type of value is supplied). The second
argument to the call method is a Controller. A Controller can be obtained
by calling the getController() method on the XQueryExpression object. The same Controller
can be used for a series of separate function calls.
For example:
Configuration config = new Configuration();
StaticQueryContext sqc = config.newStaticQueryContext();
XQueryExpression exp1 = sqc.compileQuery(
"declare namespace f='f.ns';" +
"declare function f:t1($p as xs:integer) { $p * $p };" +
"declare function f:t2($p as xs:integer) { $p + $p };" +
"1"
);
StaticQueryContext sqc2 = exp1.getStaticContext();
UserFunction fn1 = sqc2.getUserDefinedFunction("f.ns", "t1", 1);
UserFunction fn2 = sqc2.getUserDefinedFunction("f.ns", "t2", 1);
Controller controller = exp1.getController();
IntegerValue[] arglist = new IntegerValue[1];
for (int x=1; x<1000000; x++) {
arglist[0] = new IntegerValue(x);
Value v1 = fn1.call(arglist, controller);
Value v2 = fn2.call(arglist, controller);
System.err.println("Returned product " + v1 + "; sum =" + v2);
}