Hi Michael,

Just checking to see if a patch is available for the issue described below. If there's anything I can do to help, please let me know.

Best Regards,
Karthick Sankarachary

On Thu, Sep 11, 2008 at 3:29 PM, Michael Kay <mike@saxonica.com> wrote:
It looks as if I didn't run enough tests on the JAXP XPath interface. It's a pretty tough one to support because the architecture of the interface is so different from Saxon's native architecture, and it's full of XPath 1.0 assumptions. Also it's very underspecified - for example there is nothing that says what kinds of values get passed in the list of arguments to a function that's returned by a FunctionResolver. And although it's underspecified, users expect it to behave in the same way as other implementations, which can only be discovered by trial and error.
Saxon is saying "can't convert to Object" because it needs more information about what kind of object the function wants to see. But clearly to conform to JAXP we just have to guess, and pass something. In this case the function probably wants to see a DOM node, so I'll probably patch the code to provide that. However it remains the case that this interface is underspecified and undertested. I think there's a lot to be said for using the s9api interface if you want something more predictable and robust.
Incidentally, at the end of your code you cast the result to Node. Because you've asked for NODELIST, the result will be a DOM NodeList even if it only contains one node.
Michael Kay

From: Karthick Sankarachary [mailto:karthick.sankarachary@gmail.com]
Sent: 11 September 2008 21:17
To: Michael Kay

Cc: Mailing list for the SAXON XSLT and XQuery processor
Subject: Re: [saxon] Passing Nodes To XPath Functions

Hi Michael,

First off, thanks for the quick response. 

To answer your questions:

Yes, I do have saxon9-dom.jar in my classpath, along with all of the other saxon9*jars.
Yes, the function in question is an extension function. And no, I don't run into this problem with built-in functions.

For your convenience, here's a complete JUnit test case:

import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFunction;
import javax.xml.xpath.XPathFunctionException;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;

import junit.framework.TestCase;
import net.sf.saxon.om.NamespaceConstant;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

public class NodeVariableTestCase extends TestCase {
@Test public void testFunctionCall() throws Throwable {
// Initialize DOM objects
        DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
        final Document doc = docBuilder.newDocument();
        final Node node = doc.createElement("Y"); 

        // Initialize XPath
     "javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_SAXON,
        XPathFactory xpf = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
        XPath xpe = xpf.newXPath();
        // Initialize various resolvers
        xpe.setXPathVariableResolver(new XPathVariableResolver() {
public Object resolveVariable(QName variableName) {
if ("Y".equals(variableName.getLocalPart())) {
return node; 
return null;
        xpe.setXPathFunctionResolver(new XPathFunctionResolver() {
         public XPathFunction resolveFunction(QName functionName, int arity) {
         if ("X".equals(functionName.getLocalPart())) {
         return new XPathFunction() {
public Object evaluate(List args)
throws XPathFunctionException {
if (args.size() == 1) {
if (args.get(0) instanceof Node) {
return args.get(0);
return null;
         return null;
        xpe.setNamespaceContext(new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
                if (prefix.equals("saxon")) {
                    return "http://saxon.sf.net/";
                } else {
                    if (prefix.equals("tns")) {
                     return "http://my.org.com/";
                    } else 
                     return null;
       public String getPrefix(String uri) {
return null;
    public Iterator getPrefixes(String uri) {
return null;
        // Compile
        XPathExpression expr =
        // Execute
        Node result = (Node) expr.evaluate(doc, XPathConstants.NODESET);

Best Regards,
Karthick Sankarachary