Project

Profile

Help

How to use setContextItem when using callFunction

Added by Saurabh Jain almost 5 years ago

Hi,

I would like to pass a dom node to a function and extract value using XPath. I am getting Exception in thread "main" net.sf.saxon.s9api.SaxonApiException: There is no context item. Found while atomizing the first argument of fn:contains()

Here is the sample code

		Configuration configuration = Configuration.newConfiguration();
		Processor processor = new Processor(configuration);
		
		XQueryCompiler xQueryCompiler = processor.newXQueryCompiler();

		String fun = new String(Files.readAllBytes(Paths.get("query/funTest.xq")));
		XQueryEvaluator qe = xQueryCompiler.compile(fun).load();
                qe.setContextItem(new XdmAtomicValue("apple"));

		Map<String, Object> javaMap = new HashMap<>();
		javaMap.put("key1", "val1");
		javaMap.put("key2", "val1");
		javaMap.put("key3", "val1");
		javaMap.put("key4", "val1");		
		qe.setExternalVariable(new QName("javaArgs"), new XdmExternalObject(javaMap));
		
		XdmValue xdmValue = qe.callFunction(new QName(
                      "http://www.w3.org/2005/xquery-local-functions", "testJavaArgs"), new XdmValue[] {});

And content of funTest.xq

declare variable $javaArgs external; declare variable $testArgs external;

declare function local:testJavaArgs() {
  let $discount := 12
  return contains(., 'e')
};

0

However this works fine

        XQueryExecutable exp = xQueryCompiler.compile("contains(., 'e')");

        qe = exp.load();
        qe.setContextItem(new XdmAtomicValue("apple"));
        XdmValue result = qe.evaluate();
        System.out.println("apple: " + ((XdmAtomicValue) result).getBooleanValue());

Replies (3)

Please register to reply

RE: How to use setContextItem when using callFunction - Added by Michael Kay almost 5 years ago

The global context item is not available within a function body. This would be exactly the same if you set it within the query, using declare context item. You can access global variables, but not the global context item. It's a rather arbitrary rule; I think the reason for it is that many people would assume that a reference to "." within the function body was a reference to the context item of the function caller, rather than the global context item.

I suggest you use a global varaible here rather than the context item.

RE: How to use setContextItem when using callFunction - Added by Michael Kay almost 5 years ago

The relevant rule in the XQuery 3.1 spec is in §4.18:

[Definition: User defined functions are functions that contain a function body, which provides the implementation of the function as a content expression .] The static context for a function body includes all functions, variables, and namespaces that are declared or imported anywhere in the Prolog, including the function being declared. Its in-scope variables component also includes the parameters of the function being declared. However, its context item static type component is absent, and an implementation should raise a static error [err:XPST0008] if an expression depends on the context item.

RE: How to use setContextItem when using callFunction - Added by Saurabh Jain almost 5 years ago

Thanks Michael for quick response. Using global variable mechanism it works !!!

Regards Saurabh

    (1-3/3)

    Please register to reply