static void xpath_exception_handler(void * ctx, xmlErrorPtr error) { VALUE xpath = rb_const_get(mNokogiriXml, rb_intern("XPath")); VALUE klass = rb_const_get(xpath, rb_intern("SyntaxError")); rb_exc_raise(Nokogiri_wrap_xml_syntax_error(klass, error)); }
/* * call-seq: * read * * Move the Reader forward through the XML document. */ static VALUE read_more(VALUE self) { xmlTextReaderPtr reader; xmlErrorPtr error; VALUE error_list; int ret; Data_Get_Struct(self, xmlTextReader, reader); error_list = rb_funcall(self, rb_intern("errors"), 0); xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher); ret = xmlTextReaderRead(reader); xmlSetStructuredErrorFunc(NULL, NULL); if(ret == 1) return self; if(ret == 0) return Qnil; error = xmlGetLastError(); if(error) rb_exc_raise(Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error)); else rb_raise(rb_eRuntimeError, "Error pulling: %d", ret); return Qnil; }
/* * call-seq: * read_memory(string, url, encoding, options) * * Create a new document from a String */ static VALUE read_memory( VALUE klass, VALUE string, VALUE url, VALUE encoding, VALUE options ) { const char * c_buffer = StringValuePtr(string); const char * c_url = NIL_P(url) ? NULL : StringValuePtr(url); const char * c_enc = NIL_P(encoding) ? NULL : StringValuePtr(encoding); int len = (int)RSTRING_LEN(string); VALUE error_list = rb_ary_new(); xmlResetLastError(); xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher); xmlDocPtr doc = xmlReadMemory(c_buffer, len, c_url, c_enc, (int)NUM2INT(options)); xmlSetStructuredErrorFunc(NULL, NULL); if(doc == NULL) { xmlFreeDoc(doc); xmlErrorPtr error = xmlGetLastError(); if(error) rb_exc_raise(Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error)); else rb_raise(rb_eRuntimeError, "Could not parse document"); return Qnil; } VALUE document = Nokogiri_wrap_xml_document(klass, doc); rb_iv_set(document, "@errors", error_list); return document; }
/* * call-seq: * read_io(io, url, encoding, options) * * Create a new document from an IO object */ static VALUE read_io( VALUE klass, VALUE io, VALUE url, VALUE encoding, VALUE options ) { const char * c_url = NIL_P(url) ? NULL : StringValuePtr(url); const char * c_enc = NIL_P(encoding) ? NULL : StringValuePtr(encoding); VALUE error_list = rb_ary_new(); VALUE document; xmlDocPtr doc; xmlResetLastError(); Nokogiri_install_error_catcher(error_list); doc = xmlReadIO( (xmlInputReadCallback)io_read_callback, (xmlInputCloseCallback)io_close_callback, (void *)io, c_url, c_enc, (int)NUM2INT(options) ); Nokogiri_remove_error_catcher(); if(doc == NULL) { xmlErrorPtr error; xmlFreeDoc(doc); error = xmlGetLastError(); if(error) rb_exc_raise(Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error)); else rb_raise(rb_eRuntimeError, "Could not parse document"); return Qnil; } document = Nokogiri_wrap_xml_document(klass, doc); rb_iv_set(document, "@errors", error_list); return document; }
/* * call-seq: * read_io(io, url, encoding, options) * * Create a new document from an IO object */ static VALUE read_io( VALUE klass, VALUE io, VALUE url, VALUE encoding, VALUE options ) { const char * c_url = (url == Qnil) ? NULL : StringValuePtr(url); const char * c_enc = (encoding == Qnil) ? NULL : StringValuePtr(encoding); VALUE error_list = rb_ary_new(); xmlInitParser(); xmlResetLastError(); xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher); xmlDocPtr doc = xmlReadIO( (xmlInputReadCallback)io_read_callback, (xmlInputCloseCallback)io_close_callback, (void *)io, c_url, c_enc, NUM2INT(options) ); xmlSetStructuredErrorFunc(NULL, NULL); if(doc == NULL) { xmlFreeDoc(doc); xmlErrorPtr error = xmlGetLastError(); if(error) rb_funcall(rb_mKernel, rb_intern("raise"), 1, Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error) ); else rb_raise(rb_eRuntimeError, "Could not parse document"); return Qnil; } VALUE document = Nokogiri_wrap_xml_document(klass, doc); rb_funcall(document, rb_intern("errors="), 1, error_list); return document; }
/* * call-seq: * read_memory(string) * * Create a new Schema from the contents of +string+ */ static VALUE read_memory(VALUE klass, VALUE content) { xmlSchemaParserCtxtPtr ctx = xmlSchemaNewMemParserCtxt( (const char *)StringValuePtr(content), RSTRING_LEN(content) ); VALUE errors = rb_ary_new(); xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher); xmlSchemaSetParserStructuredErrors( ctx, Nokogiri_error_array_pusher, (void *)errors ); xmlSchemaPtr schema = xmlSchemaParse(ctx); xmlSetStructuredErrorFunc(NULL, NULL); xmlSchemaFreeParserCtxt(ctx); if(NULL == schema) { xmlErrorPtr error = xmlGetLastError(); if(error) rb_funcall(rb_mKernel, rb_intern("raise"), 1, Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error) ); else rb_raise(rb_eRuntimeError, "Could not parse document"); return Qnil; } VALUE rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema); rb_iv_set(rb_schema, "@errors", errors); return rb_schema; }
/* * call-seq: * evaluate(search_path, handler = nil) * * Evaluate the +search_path+ returning an XML::XPath object. */ static VALUE evaluate(int argc, VALUE *argv, VALUE self) { VALUE search_path, xpath_handler; VALUE thing = Qnil; xmlXPathContextPtr ctx; xmlXPathObjectPtr xpath; xmlChar *query; Data_Get_Struct(self, xmlXPathContext, ctx); if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) xpath_handler = Qnil; 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); 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_exc_raise(Nokogiri_wrap_xml_syntax_error(klass, error)); } assert(ctx->doc); assert(DOC_RUBY_OBJECT_TEST(ctx->doc)); switch(xpath->type) { case XPATH_STRING: thing = NOKOGIRI_STR_NEW2(xpath->stringval); break; case XPATH_NODESET: if(NULL == xpath->nodesetval) { thing = Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL), DOC_RUBY_OBJECT(ctx->doc)); } else { thing = Nokogiri_wrap_xml_node_set(xpath->nodesetval, DOC_RUBY_OBJECT(ctx->doc)); } break; case XPATH_NUMBER: thing = rb_float_new(xpath->floatval); break; case XPATH_BOOLEAN: thing = xpath->boolval == 1 ? Qtrue : Qfalse; break; default: thing = Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL), DOC_RUBY_OBJECT(ctx->doc)); } xmlXPathFreeNodeSetList(xpath); return thing; }
void Nokogiri_error_raise(void * ctx, xmlErrorPtr error) { rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error)); }
void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error) { VALUE list = (VALUE)ctx; rb_ary_push(list, Nokogiri_wrap_xml_syntax_error(error)); }
void Nokogiri_error_raise(void * ctx, xmlErrorPtr error) { rb_funcall(rb_mKernel, rb_intern("raise"), 1, Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error) ); }