ext/xml/ruby_xml_node.c in libxml-ruby-0.3.6 vs ext/xml/ruby_xml_node.c in libxml-ruby-0.3.8

- old
+ new

@@ -1,6 +1,6 @@ -/* $Id: ruby_xml_node.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */ +/* $Id: ruby_xml_node.c,v 1.3 2006/04/12 12:08:39 roscopeco Exp $ */ /* Please see the LICENSE file for copyright and distribution information */ #include "libxml.h" #include "ruby_xml_node.h" @@ -139,11 +139,11 @@ xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(obj)); return(obj); } else { str = rb_obj_as_string(obj); if (NIL_P(str) || TYPE(str) != T_STRING) - rb_raise(rb_eTypeError, "invalid argumnt: must be string or XML::Node"); + rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node"); xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(str)); return(obj); } } @@ -156,28 +156,21 @@ * Obtain this node's content as a string. */ VALUE ruby_xml_node_content_get(VALUE self) { ruby_xml_node *rxn; - + xmlChar *content; + VALUE out; + Data_Get_Struct(self, ruby_xml_node, rxn); - if (rxn->node->type == XML_ELEMENT_NODE || rxn->node->content == NULL) - return(Qnil); - else { - return(rb_str_new2((const char*)rxn->node->content)); - } + content = xmlNodeGetContent(rxn->node); + out = rb_str_new2((const char *) content); + xmlFree(content); + + return out; } -///////////////////////////////////////////// -// TODO may be bugged: -// -// node.content = "123" -// node.content => nil -// node.content_stripped => nil -// node.to_s => "<head xml:base=\"123\">wow</head>" - - /* * call-seq: * node.content = "string" * * Set this node's content to the specified string. @@ -191,19 +184,18 @@ xmlNodeSetContent(node->node, (xmlChar*)StringValuePtr(content)); return(Qtrue); } -///////////////////////////////////////////////////// -// TODO may be bugged: see above -// - /* * call-seq: * node.content_stripped => "string" * * Obtain this node's stripped content. + * + * *Deprecated*: Stripped content can be obtained via the + * +content+ method. */ VALUE ruby_xml_node_content_stripped_get(VALUE self) { ruby_xml_node *rxn; @@ -582,13 +574,35 @@ return(Qtrue); else return(Qfalse); } +VALUE ruby_xml_node_to_s(VALUE self); /* * call-seq: + * node.eql?(other_node) => (true|false) + * + * Test equality between the two nodes. Equality is determined based + * on the XML representation of the nodes. + */ +VALUE +ruby_xml_node_eql_q(VALUE self, VALUE other) { + // TODO this isn't the best way to handle this + ruby_xml_node *rxn, *orxn; + VALUE thisxml, otherxml; + Data_Get_Struct(self, ruby_xml_node, rxn); + Data_Get_Struct(other, ruby_xml_node, orxn); + thisxml = ruby_xml_node_to_s(self); + otherxml = ruby_xml_node_to_s(other); + + return(rb_funcall(thisxml, rb_intern("=="), 1, otherxml)); +} + + +/* + * call-seq: * node.find(xpath_expr, namespace = [any]) => nodeset * * Find nodes matching the specified xpath expression, optionally * using the specified namespaces. Returns an XML::Node::Set. */ @@ -607,11 +621,39 @@ vargv[i + 1] = argv[i]; return(ruby_xml_xpath_find2(vargc, vargv)); } +/* + * call-seq: + * node.find_first(xpath_expr, namespace = [any]) => nodeset + * + * Find the first node matching the specified xpath expression, optionally + * using the specified namespaces. Returns an XML::Node. + */ +VALUE +ruby_xml_node_find_first(int argc, VALUE *argv, VALUE self) { + VALUE ns = ruby_xml_node_find(argc, argv, self); + ruby_xml_node_set *rxnset; + Data_Get_Struct(ns, ruby_xml_node_set, rxnset); + if (rxnset->node_set == NULL || rxnset->node_set->nodeNr < 1) + return(Qnil); + + VALUE nodeobj; + switch(rxnset->node_set->nodeTab[0]->type) { + case XML_ATTRIBUTE_NODE: + nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[0]); + break; + default: + nodeobj = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]); + } + + return(nodeobj); +} + + /* * call-seq: * node.fragment? => (true|false) * * Determine whether this node is a fragment. @@ -638,10 +680,28 @@ } /* * call-seq: + * node.hash => fixnum + * + * Returns the hash-code for this node. This is the hash of the XML + * representation in order to be consistent with eql. + */ +VALUE +ruby_xml_node_hash(VALUE self) { + ruby_xml_node *rxn; + VALUE thisxml; + Data_Get_Struct(self, ruby_xml_node, rxn); + thisxml = ruby_xml_node_to_s(self); + + return(rb_funcall(thisxml, rb_intern("hash"), 0)); +} + + +/* + * call-seq: * node.html_doc? => (true|false) * * Determine whether this node is an html document node. */ VALUE @@ -1597,14 +1657,21 @@ ruby_xml_node *node; ruby_xml_attr *rxa; xmlAttrPtr attr; VALUE rattr; - Check_Type(key, T_STRING); - Check_Type(val, T_STRING); Data_Get_Struct(self, ruby_xml_node, node); - + Check_Type(key, T_STRING); + + if( val == Qnil ) { + attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), NULL); + xmlRemoveProp( attr ); + return Qnil; + } else { + Check_Type(val, T_STRING); + } + attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), (xmlChar*)StringValuePtr(val)); if (attr == NULL) { attr = xmlNewProp(node->node, (xmlChar*)StringValuePtr(key), (xmlChar*)StringValuePtr(val)); if (attr == NULL) return(Qnil); @@ -1656,10 +1723,25 @@ } /* * call-seq: +* node.remove! => nil +* +* Removes this node from it's parent. +*/ +VALUE +ruby_xml_node_remove_ex(VALUE self) { + ruby_xml_node *rxn; + Data_Get_Struct(self, ruby_xml_node, rxn); + xmlUnlinkNode(rxn->node); + return(Qnil); +} + + +/* + * call-seq: * node.search_href => namespace * * Search for a namespace by href. */ VALUE @@ -1798,11 +1880,10 @@ Data_Get_Struct(self, ruby_xml_node, rxn); buf = xmlBufferCreate(); xmlNodeDump(buf, rxn->node->doc, rxn->node, 0, 1); result = rb_str_new2((const char*)buf->content); - // TODO result = rb_str_new2((const char*)buf->content); ? xmlBufferFree(buf); return result; } @@ -2002,12 +2083,15 @@ rb_define_method(cXMLNode, "element?", ruby_xml_node_element_q, 0); rb_define_method(cXMLNode, "element_decl?", ruby_xml_node_element_decl_q, 0); rb_define_method(cXMLNode, "empty?", ruby_xml_node_empty_q, 0); rb_define_method(cXMLNode, "entity?", ruby_xml_node_entity_q, 0); rb_define_method(cXMLNode, "entity_ref?", ruby_xml_node_entity_ref_q, 0); + rb_define_method(cXMLNode, "eql?", ruby_xml_node_eql_q, 1); rb_define_method(cXMLNode, "find", ruby_xml_node_find, -1); + rb_define_method(cXMLNode, "find_first", ruby_xml_node_find_first, -1); rb_define_method(cXMLNode, "fragment?", ruby_xml_node_fragment_q, 0); + rb_define_method(cXMLNode, "hash", ruby_xml_node_hash, 0); rb_define_method(cXMLNode, "html_doc?", ruby_xml_node_html_doc_q, 0); rb_define_method(cXMLNode, "lang", ruby_xml_node_lang_get, 0); rb_define_method(cXMLNode, "lang=", ruby_xml_node_lang_set, 1); rb_define_method(cXMLNode, "last", ruby_xml_node_last_get, 0); rb_define_method(cXMLNode, "last?", ruby_xml_node_last_q, 0); @@ -2035,10 +2119,11 @@ rb_define_method(cXMLNode, "prev", ruby_xml_node_prev_get, 0); rb_define_method(cXMLNode, "prev?", ruby_xml_node_prev_q, 0); rb_define_method(cXMLNode, "property", ruby_xml_node_property_get, 1); rb_define_method(cXMLNode, "properties", ruby_xml_node_properties_get, 0); rb_define_method(cXMLNode, "properties?", ruby_xml_node_properties_q, 0); + rb_define_method(cXMLNode, "remove!", ruby_xml_node_remove_ex, 0); rb_define_method(cXMLNode, "search_ns", ruby_xml_node_search_ns, 1); rb_define_method(cXMLNode, "search_href", ruby_xml_node_search_href, 1); rb_define_method(cXMLNode, "sibling=", ruby_xml_node_sibling_set, 1); rb_define_method(cXMLNode, "space_preserve", ruby_xml_node_space_preserve_get, 0); rb_define_method(cXMLNode, "space_preserve=", ruby_xml_node_space_preserve_set, 1); @@ -2047,6 +2132,8 @@ rb_define_method(cXMLNode, "xinclude_end?", ruby_xml_node_xinclude_end_q, 0); rb_define_method(cXMLNode, "xinclude_start?", ruby_xml_node_xinclude_start_q, 0); rb_define_method(cXMLNode, "xlink?", ruby_xml_node_xlink_q, 0); rb_define_method(cXMLNode, "xlink_type", ruby_xml_node_xlink_type, 0); rb_define_method(cXMLNode, "xlink_type_name", ruby_xml_node_xlink_type_name, 0); + + rb_define_alias(cXMLNode, "==", "eql?"); }