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?");
}