Project

Profile

Help

Any working example of set_parameter on PyXPathProcessor?

Added by Martin Honnen about 5 years ago

Even after the fix on make_string_value I am struggling to use a parameter in XPath evaluation in the Python API of Saxon/C 1.2.0 on Windows with Python 3.7.

The following program using XQuery runs fine now:

import saxonc

s1 = 'This is a test.'

with saxonc.PySaxonProcessor(license=False) as proc:
    print(proc.version)

    xdm_string_value = proc.make_string_value(s1)

    print(xdm_string_value)

    xquery_processor = proc.new_xquery_processor()

    xquery_processor.set_parameter('s1', xdm_string_value)

    result = xquery_processor.run_query_to_value(query_text = 'declare variable $s1 external; $s1')

    print(result)

    print(result.get_atomic_value().string_value)

However, the same code used with XPath crashes:

import saxonc

s1 = 'This is a test.'

with saxonc.PySaxonProcessor(license=False) as proc:
    print(proc.version)

    xdm_string_value = proc.make_string_value(s1)

    print(xdm_string_value)

    xpath_processor = proc.new_xpath_processor()

    xpath_processor.set_parameter('s1', xdm_string_value)

    result = xpath_processor.evaluate('$s1')

    print(result)

    print(result.get_atomic_value().string_value)

giving

Saxon/C 1.2.0 running with Saxon-HE 9.9.1.5J from Saxonica
This is a test.

JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x00000000004546d6
Please, contact the vendor of the application.

I have tried to find a sample in the Python examples using set_parameter on an PyXPathProcessor but I can't find anything.


Replies (12)

Please register to reply

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

Yes there is still a bug here in the code. There is a segmentation error in RefCount method for the SaxonProcessor. I have created a new bug issue for this one: #4351

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

So I have managed to put some conditional statements in the evaluate method for both the C++ and Python code to check for when the underlying evaluate Java code is running NULL. Now I need to understand why the evaluate method is returning NULL. Perhaps the s1 parameter is not being set on the XPath query.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by Martin Honnen about 5 years ago

I have now tried a similar code sample directly on the C++ side with

void testXPathStringParameter(SaxonProcessor * processor, XPathProcessor * xpath) {
	cout << endl << "Test testXPathStringParameter:" << endl;
	xpath->clearParameters(true);
	xpath->clearProperties();

	XdmAtomicValue *stringValue = processor->makeStringValue("This is a test.");

	cout << "string parameter passsed to XPath: " << stringValue->getStringValue() << endl;

	xpath->setParameter("s1", (XdmValue*)stringValue);

	XdmItem *result = xpath->evaluateSingle("$s1");

	if (result == NULL) {
		printf("result is null \n");
	}
	else {
		cout << "Number of items=" << result->size() << endl;
		cout << "String Value of result=" << result->getStringValue() << endl;
	}

	delete result;

}

and the result is NULL.

Is the C++ API lacking a method to declare parameters for XPath evaluation, like http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/XPathSelector.html#setVariable-net.sf.saxon.s9api.QName-net.sf.saxon.s9api.XdmValue- on the Java side?

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

In the python script I added the following code to debug if we have any errors caught in Saxon/C:

    if xpath_processor.exception_count() > 0:
        print(xpath_processor.get_error_message(0)

Output in terminal:

net.sf.saxon.s9api.SaxonApiException : Undeclared variable in XPath expression: $s1

The XPathProcessor API for C++, Python and PHP does not have a declareVariable method as in the Java class XPathCompiler. There is no real workaround for this issue. A fix will be in the next maintenance release.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

The workaround would be to use the XQuery API.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by Martin Honnen about 5 years ago

Well, I started with a working XQuery sample but in general, even if it allows me to pass in a variable, I don't get far with XQuery either, the following crashes:

import saxonc

n = 10

with saxonc.PySaxonProcessor(license=False) as proc:
    print(proc.version)

    xdm_int_value = proc.make_integer_value(n)

    print(xdm_int_value)

    xquery_processor = proc.new_xquery_processor()

    xquery_processor.set_parameter('n', xdm_int_value)

    result = xquery_processor.run_query_to_value(query_text = 'declare variable $n external; (1 to $n)!(. * .)')
   
    print(result.size)

    for i in range(result.size):
        print(result.item_at(i))

Output:

Saxon/C 1.2.0 running with Saxon-HE 9.9.1.5J from Saxonica
10
1

JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000428b82

I guess the whole stuff, at least propagating values from Saxon to Python, needs to mature a bit more.

Even without the use of set_parameter it crashes:

with saxonc.PySaxonProcessor(license=False) as proc:
    print(proc.version)

    xquery_processor = proc.new_xquery_processor()

    result = xquery_processor.run_query_to_value(query_text = 'declare variable $n external := 10; (1 to $n)!(. * .)')
   
    print(result.size)

    for i in range(result.size):
        print(result.item_at(i))

Or is that just a Windows issue?

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

I will investigate this in a separate bug issue. I think the issue of handling the memory of created XdmValue objects will take a few iterations to get right. Thank you for the feedback.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

The issue is we are not handling properly the case where the `XdmValue is a sequence.

In the C++ code we are checking if the XdmValue is an instance of XdmNode or XdmtomicValue. But if it is neither of these types we just wrap the Java XdmValue object in the wrapper class in C++. This is no good in the case where the XdmValue contains a sequence value like a SequenceExtent object. In the Xslt30Processor object we handle this case by building sequence of items on the C++ side, but this code we are just not using in the XQueryProcessor.

I have made the fix in the C++ code and the sample above works now. I will commit the patch to the C++ later today after I have done some more testing for you to try.

I initially thought this was a memory issue but this is not the case.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

I have created the bug issue #4352 for keeping track of the progress.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

Bug fixed and committed to subversion. Available in the next maintenance release, but can be applied by downloading the files mentioned in the bug issue #4352

RE: Any working example of set_parameter on PyXPathProcessor? - Added by Martin Honnen about 5 years ago

Great work, most stuff I have tried with the to_value methods now works, what keeps from easily outputting a complete sequence with a direct print is the issue in https://saxonica.plan.io/boards/4/topics/7610.

RE: Any working example of set_parameter on PyXPathProcessor? - Added by O'Neil Delpratt about 5 years ago

Martin Honnen wrote:

Great work, most stuff I have tried with the to_value methods now works, what keeps from easily outputting a complete sequence with a direct print is the issue in https://saxonica.plan.io/boards/4/topics/7610.

The issue mentioned in the post https://saxonica.plan.io/boards/4/topics/7610 has now been fixed here #4352

    (1-12/12)

    Please register to reply