/* * 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); VALUE error_list = rb_ary_new(); 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((void *)error_list, Nokogiri_error_array_pusher); xmlXPathObjectPtr xpath = xmlXPathEvalExpression(query, ctx); xmlSetStructuredErrorFunc(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(ctx->doc->_private); rb_funcall( xpath_object, rb_intern("document="), 1, (VALUE)ctx->doc->_private ); return xpath_object; }