/* call-seq: * context.register_namespaces_from_node(node) -> self * * Helper method to read in namespaces defined on a node. * * doc = XML::Document.string('<header><first>hi</first></header>') * context = XPath::Context.new(doc) * context.register_namespaces_from_node(doc.root) */ static VALUE rxml_xpath_context_register_namespaces_from_node(VALUE self, VALUE node) { xmlXPathContextPtr xctxt; xmlNodePtr xnode; xmlNsPtr *xnsArr; Data_Get_Struct(self, xmlXPathContext, xctxt); if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue) { xmlDocPtr xdoc; Data_Get_Struct(node, xmlDoc, xdoc); xnode = xmlDocGetRootElement(xdoc); } else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue) { Data_Get_Struct(node, xmlNode, xnode); } else { rb_raise(rb_eTypeError, "The first argument must be a document or node."); } xnsArr = xmlGetNsList(xnode->doc, xnode); if (xnsArr) { xmlNsPtr xns = *xnsArr; while (xns) { /* If there is no prefix, then this is the default namespace. Skip it for now. */ if (xns->prefix) { VALUE prefix = rxml_str_new2((const char*)xns->prefix, xctxt->doc->encoding); VALUE uri = rxml_str_new2((const char*)xns->href, xctxt->doc->encoding); rxml_xpath_context_register_namespace(self, prefix, uri); } xns = xns->next; } xmlFree(xnsArr); } return self; }
/* * call-seq: * context.register_namespaces(["prefix:uri"]) -> self * * Register the specified namespaces in this context. There are * three different forms that libxml accepts. These include * a string, an array of strings, or a hash table: * * context.register_namespaces('xi:http://www.w3.org/2001/XInclude') * context.register_namespaces(['xlink:http://www.w3.org/1999/xlink', * 'xi:http://www.w3.org/2001/XInclude') * context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink', * 'xi' => 'http://www.w3.org/2001/XInclude') */ static VALUE rxml_xpath_context_register_namespaces(VALUE self, VALUE nslist) { char *cp; long i; VALUE rprefix, ruri; xmlXPathContextPtr xctxt; Data_Get_Struct(self, xmlXPathContext, xctxt); /* Need to loop through the 2nd argument and iterate through the * list of namespaces that we want to allow */ switch (TYPE(nslist)) { case T_STRING: cp = strchr(StringValuePtr(nslist), (int) ':'); if (cp == NULL) { rprefix = nslist; ruri = Qnil; } else { rprefix = rb_str_new(StringValuePtr(nslist), (int) ((long) cp - (long) StringValuePtr(nslist))); ruri = rxml_str_new2(&cp[1], xctxt->doc->encoding); } /* Should test the results of this */ rxml_xpath_context_register_namespace(self, rprefix, ruri); break; case T_ARRAY: for (i = 0; i < RARRAY_LEN(nslist); i++) { rxml_xpath_context_register_namespaces(self, RARRAY_PTR(nslist)[i]); } break; case T_HASH: rb_hash_foreach(nslist, iterate_ns_hash, self); break; default: rb_raise( rb_eArgError, "Invalid argument type, only accept string, array of strings, or an array of arrays"); } return self; }
static int iterate_ns_hash(VALUE prefix, VALUE uri, VALUE self) { rxml_xpath_context_register_namespace(self, prefix, uri); return ST_CONTINUE; }
static int iterate_ns_hash(st_data_t prefix, st_data_t uri, st_data_t self) { rxml_xpath_context_register_namespace(self, prefix, uri); return ST_CONTINUE; }