/* $Id: ruby_xml_xpath.c,v 1.9 2002/10/22 07:56:53 sean Exp $ */ /* Please see the LICENSE file for copyright and distribution information */ #include "libxml.h" #include "ruby_xml_xpath.h" VALUE cXMLXPath; VALUE eXMLXPathInvalidPath; #ifdef LIBXML_XPATH_ENABLED VALUE ruby_xml_xpath_debug(VALUE self) { #ifdef LIBXML_DEBUG_ENABLED ruby_xml_xpath *rxxp; Data_Get_Struct(self, ruby_xml_xpath, rxxp); if (rxxp->xpop != NULL) { xmlXPathDebugDumpObject(stdout, rxxp->xpop, 0); return(Qtrue); } else { return(Qfalse); } #else rb_warn("libxml does not have debugging turned on"); return(Qfalse); #endif } VALUE ruby_xml_xpath_each(VALUE self) { ruby_xml_xpath *rxxp; VALUE rxnset; Data_Get_Struct(self, ruby_xml_xpath, rxxp); rxnset = ruby_xml_node_set_new(cXMLNodeSet, rxxp->xd, self, rxxp->xpop->nodesetval); ruby_xml_node_set_each(rxnset); return(rxnset); } VALUE ruby_xml_xpath_find(VALUE class, VALUE rnode, VALUE string) { #ifdef LIBXML_XPATH_ENABLED xmlXPathCompExprPtr comp; ruby_xml_node *node; ruby_xml_xpath *rxxp; ruby_xml_xpath_context *rxxpc; VALUE xxpc, xpath; Check_Type(string, T_STRING); if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse) rb_raise(rb_eTypeError, "require an XML::Node object"); Data_Get_Struct(rnode, ruby_xml_node, node); xxpc = ruby_xml_xpath_context_new4(rnode); if (NIL_P(xxpc)) return(Qnil); Data_Get_Struct(xxpc, ruby_xml_xpath_context, rxxpc); xpath = ruby_xml_xpath_new(cXMLXPath, rnode, xxpc, NULL); Data_Get_Struct(xpath, ruby_xml_xpath, rxxp); rxxpc->ctxt->node = node->node; comp = xmlXPathCompile(STR2CSTR(string)); if (comp == NULL) { xmlXPathFreeCompExpr(comp); rb_raise(eXMLXPathInvalidPath, "Invalid XPath expression"); } rxxp->xpop = xmlXPathCompiledEval(comp, rxxpc->ctxt); xmlXPathFreeCompExpr(comp); if (rxxp->xpop == NULL) rb_raise(eXMLXPathInvalidPath, "Invalid XPath expression for this document"); return(ruby_xml_node_set_new2(node->xd, xpath, rxxp->xpop->nodesetval)); #else rb_warn("libxml was compiled without XPath support"); return(Qfalse); #endif } VALUE ruby_xml_xpath_find2(VALUE node, VALUE string) { return(ruby_xml_xpath_find(cXMLXPath, node, string)); } void ruby_xml_xpath_free(ruby_xml_xpath *rxxp) { if (rxxp->xpop != NULL) xmlXPathFreeObject(rxxp->xpop); free(rxxp); } void ruby_xml_xpath_mark(ruby_xml_xpath *rxxp) { if (rxxp == NULL) return; if (!NIL_P(rxxp->ctxt)) rb_gc_mark(rxxp->ctxt); if (!NIL_P(rxxp->xd)) rb_gc_mark(rxxp->xd); } VALUE ruby_xml_xpath_new(VALUE class, VALUE xd, VALUE ctxt, xmlXPathObjectPtr xpop) { ruby_xml_xpath *rxxp; rxxp = ALLOC(ruby_xml_xpath); rxxp->ctxt = ctxt; rxxp->xd = xd; rxxp->xpop = xpop; return(Data_Wrap_Struct(class, ruby_xml_xpath_mark, ruby_xml_xpath_free, rxxp)); } VALUE ruby_xml_xpath_set(VALUE self) { ruby_xml_xpath *rxxp; Data_Get_Struct(self, ruby_xml_xpath, rxxp); return(ruby_xml_node_set_new(cXMLNodeSet, rxxp->xd, self, rxxp->xpop->nodesetval)); } VALUE ruby_xml_xpath_set_type(VALUE self) { ruby_xml_xpath *rxxp; Data_Get_Struct(self, ruby_xml_xpath, rxxp); return(INT2FIX(rxxp->xpop->type)); } VALUE ruby_xml_xpath_string(VALUE self) { ruby_xml_xpath *rxxp; Data_Get_Struct(self, ruby_xml_xpath, rxxp); if (rxxp->xpop->stringval == NULL) return(Qnil); else return(rb_str_new2(rxxp->xpop->stringval)); } void ruby_init_xml_xpath(void) { cXMLXPath = rb_define_class_under(mXML, "XPath", rb_cObject); eXMLXPathInvalidPath = rb_define_class_under(cXMLXPath, "InvalidPath", rb_eException); rb_define_const(cXMLXPath, "UNDEFINED", INT2NUM(XPATH_UNDEFINED)); rb_define_const(cXMLXPath, "NODESET", INT2NUM(XPATH_NODESET)); rb_define_const(cXMLXPath, "BOOLEAN", INT2NUM(XPATH_BOOLEAN)); rb_define_const(cXMLXPath, "NUMBER", INT2NUM(XPATH_NUMBER)); rb_define_const(cXMLXPath, "STRING", INT2NUM(XPATH_STRING)); rb_define_const(cXMLXPath, "POINT", INT2NUM(XPATH_POINT)); rb_define_const(cXMLXPath, "RANGE", INT2NUM(XPATH_RANGE)); rb_define_const(cXMLXPath, "LOCATIONSET", INT2NUM(XPATH_LOCATIONSET)); rb_define_const(cXMLXPath, "USERS", INT2NUM(XPATH_USERS)); rb_define_const(cXMLXPath, "XSLT_TREE", INT2NUM(XPATH_XSLT_TREE)); rb_define_singleton_method(cXMLXPath, "find", ruby_xml_xpath_find, 2); rb_define_method(cXMLXPath, "debug", ruby_xml_xpath_debug, 0); rb_define_method(cXMLXPath, "each", ruby_xml_xpath_each, 0); rb_define_method(cXMLXPath, "set", ruby_xml_xpath_set, 0); rb_define_method(cXMLXPath, "set_type", ruby_xml_xpath_set_type, 0); rb_define_method(cXMLXPath, "string", ruby_xml_xpath_string, 0); } #endif /* ifdef LIBXML_XPATH_ENABLED */