/*
* call-seq:
* evaluate(search_path)
*
* Evaluate the +search_path+ returning an XML::XPath object.
*/
static VALUE evaluate(int argc, VALUE *argv, VALUE self)
{
VALUE search_path, xpath_handler;
xmlXPathContextPtr ctx;
Data_Get_Struct(self, xmlXPathContext, ctx);
if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1)
xpath_handler = Qnil;
xmlChar* query = (xmlChar *)StringValuePtr(search_path);
if(Qnil != xpath_handler) {
// FIXME: not sure if this is the correct place to shove private data.
ctx->userData = (void *)xpath_handler;
xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler);
}
xmlResetLastError();
xmlSetStructuredErrorFunc(NULL, xpath_exception_handler);
// For some reason, xmlXPathEvalExpression will blow up with a generic error
// when there is a non existent function.
xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
xmlXPathObjectPtr xpath = xmlXPathEvalExpression(query, ctx);
xmlSetStructuredErrorFunc(NULL, NULL);
xmlSetGenericErrorFunc(NULL, NULL);
if(xpath == NULL) {
VALUE xpath = rb_const_get(mNokogiriXml, rb_intern("XPath"));
VALUE klass = rb_const_get(xpath, rb_intern("SyntaxError"));
xmlErrorPtr error = xmlGetLastError();
rb_funcall(rb_mKernel, rb_intern("raise"), 1,
Nokogiri_wrap_xml_syntax_error(klass, error)
);
}
VALUE xpath_object = Nokogiri_wrap_xml_xpath(xpath);
assert(ctx->doc);
assert(DOC_RUBY_OBJECT_TEST(ctx->doc));
rb_funcall( xpath_object,
rb_intern("document="),
1,
DOC_RUBY_OBJECT(ctx->doc)
);
return xpath_object;
}