javaxpathxsltsaxon

Saxon9: How do I get the declared variables from the net.sf.saxon.expr.XPathContext in a Java extension function


I have declared several Java extension functions by implementing my own net.sf.saxon.functions.JavaExtensionLibrary and passing it to the net.sf.saxon.Configuration and thereby to the net.sf.saxon.TransformerFactoryImpl. This works fine so far. Saxon passes a net.sf.saxon.expr.XPathContext object when calling my methods. Is there a way to get the declared xsl variables with their values and/or their definitions from this XPathContext? I could only find the global variables (declared at the top level of the xsl stylesheet), but not the ones declared later in the XSL code. Ideally, I would like to enumerate the variables.

I got the global xsl variables only by calling

context.getController().getExecutable().getCompiledGlobalVariables()

I was hoping to get similar information for all the variables that are available at that point in the XSL code, even when they were declared later.


Solution

  • You need to be aware that you're dealing with internal APIs here that could change from release to release.

    XPathContext.getStackFrame() will give you the current stack frame holding local variables; but you may need to go back to the caller's context using XPathContext.getCaller(). The StackFrame object has a method getStackFrameMap() which gives you a SlotManager object which holds a mapping from variable names to integer slot numbers (be aware that several local variables may have the same name), and StackFrame.getStackFrameValues() gives you an array holding the actual variable values (assuming they have already been evaluated).

    There are many potential pitfalls in doing this kind of thing. For example you'll find that some of the local variables are system-allocated (supporting optimizations such as loop-lifting), and some of the user-declared local variables may have been optimized away. The fact that variables are sometimes lazily-evaluated poses additional challenges.