/* $Id: ruby_xml_node.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
/* Please see the LICENSE file for copyright and distribution information */
#include "libxml.h"
#include "ruby_xml_node.h"
VALUE cXMLNode;
VALUE eXMLNodeSetNamespace;
VALUE eXMLNodeFailedModify;
VALUE eXMLNodeUnknownType;
/*
* call-seq:
* node.attribute? => (true|false)
*
* Determine whether this is an attribute node,
*/
VALUE
ruby_xml_node_attribute_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ATTRIBUTE_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.attribute_decl? => (true|false)
*
* Determine whether this is an attribute declaration node,
*/
VALUE
ruby_xml_node_attribute_decl_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ATTRIBUTE_DECL)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.base => "uri"
*
* Obtain this node's base URI.
*/
VALUE
ruby_xml_node_base_get(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->doc == NULL)
return(Qnil);
// TODO some NULL checking, raises ArgumentError in Ruby:
// ArgumentError: NULL pointer given
return(rb_str_new2((const char*)xmlNodeGetBase(rxn->node->doc, rxn->node)));
}
// TODO node_base_set should support setting back to nil
/*
* call-seq:
* node.base = "uri"
*
* Set this node's base URI.
*/
VALUE
ruby_xml_node_base_set(VALUE self, VALUE uri) {
ruby_xml_node *node;
Check_Type(uri, T_STRING);
Data_Get_Struct(self, ruby_xml_node, node);
if (node->node->doc == NULL)
return(Qnil);
xmlNodeSetBase(node->node, (xmlChar*)StringValuePtr(uri));
return(Qtrue);
}
/*
* call-seq:
* node.cdata? => (true|false)
*
* Determine whether this is a #CDATA node
*/
VALUE
ruby_xml_node_cdata_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_CDATA_SECTION_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.comment? => (true|false)
*
* Determine whether this is a comment node
*/
VALUE
ruby_xml_node_comment_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_COMMENT_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node << ("string" | node)
*
* Add the specified string or XML::Node to this node's
* content.
*/
VALUE
ruby_xml_node_content_add(VALUE self, VALUE obj) {
ruby_xml_node *node;
VALUE str;
Data_Get_Struct(self, ruby_xml_node, node);
if (rb_obj_is_kind_of(obj, cXMLNode)) {
return(ruby_xml_node_child_set(self, obj));
} else if (TYPE(obj) == T_STRING) {
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");
xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(str));
return(obj);
}
}
/*
* call-seq:
* node.content => "string"
*
* Obtain this node's content as a string.
*/
VALUE
ruby_xml_node_content_get(VALUE self) {
ruby_xml_node *rxn;
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));
}
}
/////////////////////////////////////////////
// TODO may be bugged:
//
// node.content = "123"
// node.content => nil
// node.content_stripped => nil
// node.to_s => "
wow"
/*
* call-seq:
* node.content = "string"
*
* Set this node's content to the specified string.
*/
VALUE
ruby_xml_node_content_set(VALUE self, VALUE content) {
ruby_xml_node *node;
Check_Type(content, T_STRING);
Data_Get_Struct(self, ruby_xml_node, node);
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.
*/
VALUE
ruby_xml_node_content_stripped_get(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->content == NULL)
return(Qnil);
else
return(rb_str_new2((const char*)xmlNodeGetContent(rxn->node)));
}
////////////////////////////////////////////////////
// TODO This whole child thing seems to work in some odd ways.
// Try setting child= to a node with multiple children,
// then get it back through child= .
/*
* call-seq:
* node.child => node
*
* Obtain this node's first child node, if any.
*/
VALUE
ruby_xml_node_child_get(VALUE self) {
ruby_xml_node *node;
xmlNodePtr tmp;
Data_Get_Struct(self, ruby_xml_node, node);
switch (node->node->type) {
case XML_ELEMENT_NODE:
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
case XML_DTD_NODE:
tmp = node->node->children;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) node->node;
tmp = attr->children;
break;
}
default:
tmp = NULL;
break;
}
if (tmp == NULL)
return(Qnil);
else
return(ruby_xml_node_new2(cXMLNode, node->xd, tmp));
}
/*
* call-seq:
* node.child? => (true|false)
*
* Determine whether this node has at least one child.
*/
VALUE
ruby_xml_node_child_q(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
node = NULL;
switch (rxn->node->type) {
case XML_ELEMENT_NODE:
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
case XML_DTD_NODE:
node = rxn->node->children;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = attr->children;
break;
}
default:
node = NULL;
}
if (node == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.child = node
*
* Set a child node for this node.
*/
VALUE
ruby_xml_node_child_set(VALUE self, VALUE rnode) {
ruby_xml_node *cnode, *pnode;
xmlNodePtr ret;
if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
Data_Get_Struct(self, ruby_xml_node, pnode);
Data_Get_Struct(rnode, ruby_xml_node, cnode);
ret = xmlAddChild(pnode->node, cnode->node);
if (ret == NULL)
rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
ruby_xml_node_set_ptr(rnode, 1);
return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
}
////////////////////////////////////////////////
// TODO new Documents seem to be created quite readily...
/*
* call-seq:
* node.doc => document
*
* Obtain the XML::Document this node belongs to.
*/
VALUE
ruby_xml_node_doc(VALUE self) {
ruby_xml_document *rxd;
ruby_xml_node *rxn;
xmlDocPtr doc;
VALUE docobj;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
doc = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
doc = attr->doc;
break;
}
case XML_NAMESPACE_DECL:
doc = NULL;
break;
default:
doc = rxn->node->doc;
break;
}
if (doc == NULL)
return(Qnil);
docobj = ruby_xml_document_new(cXMLDocument, doc);
Data_Get_Struct(docobj, ruby_xml_document, rxd);
rxd->is_ptr = 1;
return(docobj);
}
/*
* call-seq:
* node.docbook? => (true|false)
*
* Determine whether this is a docbook node.
*/
VALUE
ruby_xml_node_docbook_doc_q(VALUE self) {
#ifdef LIBXML_DOCB_ENABLED
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_DOCB_DOCUMENT_NODE)
return(Qtrue);
else
return(Qfalse);
#else
rb_warn("libxml compiled without docbook support");
return(Qfalse);
#endif
}
/*
* call-seq:
* node.doctype? => (true|false)
*
* Determine whether this is a DOCTYPE node.
*/
VALUE
ruby_xml_node_doctype_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_DOCUMENT_TYPE_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.document? => (true|false)
*
* Determine whether this is a document node.
*/
VALUE
ruby_xml_node_document_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_DOCUMENT_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.dtd? => (true|false)
*
* Determine whether this is a DTD node.
*/
VALUE
ruby_xml_node_dtd_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_DTD_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.dump => (true|nil)
*
* Dump this node to stdout.
*/
VALUE
ruby_xml_node_dump(VALUE self) {
ruby_xml_node *rxn;
xmlBufferPtr buf;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->doc == NULL)
return(Qnil);
buf = xmlBufferCreate();
xmlNodeDump(buf, rxn->node->doc, rxn->node, 0, 1);
xmlBufferDump(stdout, buf);
xmlBufferFree(buf);
return(Qtrue);
}
/*
* call-seq:
* node.debug_dump => (true|nil)
*
* Dump this node to stdout, including any debugging
* information.
*/
VALUE
ruby_xml_node_debug_dump(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->doc == NULL)
return(Qnil);
xmlElemDump(stdout, rxn->node->doc, rxn->node);
return(Qtrue);
}
/*
* call-seq:
* node.element? => (true|false)
*
* Determine whether this is an element node.
*/
VALUE
ruby_xml_node_element_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ELEMENT_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.element_decl? => (true|false)
*
* Determine whether this is an element declaration node.
*/
VALUE
ruby_xml_node_element_decl_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ELEMENT_DECL)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.empty? => (true|false)
*
* Determine whether this node is empty.
*/
VALUE
ruby_xml_node_empty_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node == NULL)
return(Qnil);
return((xmlIsBlankNode(rxn->node) == 1) ? Qtrue : Qfalse);
}
/*
* call-seq:
* node.entity? => (true|false)
*
* Determine whether this is an entity node.
*/
VALUE
ruby_xml_node_entity_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ENTITY_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.entity_ref? => (true|false)
*
* Determine whether this is an entity reference node.
*/
VALUE
ruby_xml_node_entity_ref_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ENTITY_REF_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* 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.
*/
VALUE
ruby_xml_node_find(int argc, VALUE *argv, VALUE self) {
int i, vargc;
VALUE *vargv;
if (argc > 2 || argc < 1)
rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
vargc = argc + 1;
vargv = ALLOC_N(VALUE, vargc + 1);
vargv[0] = self;
for (i = 0; i (true|false)
*
* Determine whether this node is a fragment.
*/
VALUE
ruby_xml_node_fragment_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_DOCUMENT_FRAG_NODE)
return(Qtrue);
else
return(Qfalse);
}
void ruby_xml_node_free(ruby_xml_node *rxn) {
if (rxn->node != NULL && !rxn->is_ptr) {
xmlUnlinkNode(rxn->node);
xmlFreeNode(rxn->node);
rxn->node = NULL;
}
free(rxn);
}
/*
* call-seq:
* node.html_doc? => (true|false)
*
* Determine whether this node is an html document node.
*/
VALUE
ruby_xml_node_html_doc_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_HTML_DOCUMENT_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* XML::Node.new(name, content = nil) => node
*
* Create a new node with the specified name, optionally setting
* the node's content.
*/
VALUE
ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
ruby_xml_node *rxn;
VALUE name, node, str;
str = Qnil;
switch(argc) {
case 2:
switch (TYPE(str)) {
case T_STRING:
str = argv[1];
break;
default:
str = rb_obj_as_string(argv[1]);
if (NIL_P(str))
Check_Type(str, T_STRING);
break;
}
/* Intentionally fall through to case 1: as a way of setting up
* the object. Sneaky, but effective. Probably should use a goto
* instead. */
case 1:
name = argv[0];
Check_Type(name, T_STRING);
node = ruby_xml_node_new(class, NULL);
Data_Get_Struct(node, ruby_xml_node, rxn);
rxn->node = xmlNewNode(NULL, (xmlChar*)StringValuePtr(name));
if (rxn->node == NULL)
return(Qnil);
if (!NIL_P(str))
ruby_xml_node_content_set(node, str);
break;
default:
rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
}
return(node);
}
/*
* call-seq:
* node.lang => "string"
*
* Obtain the language set for this node, if any.
* This is set in XML via the xml:lang attribute.
*/
VALUE
ruby_xml_node_lang_get(VALUE self) {
ruby_xml_node *rxn;
xmlChar *lang;
Data_Get_Struct(self, ruby_xml_node, rxn);
lang = xmlNodeGetLang(rxn->node);
if (lang == NULL)
return(Qnil);
else
return(rb_str_new2((const char*)lang));
}
// TODO node_lang_set should support setting back to nil
/*
* call-seq:
* node.lang = "string"
*
* Set the language for this node. This affects the value
* of the xml:lang attribute.
*/
VALUE
ruby_xml_node_lang_set(VALUE self, VALUE lang) {
ruby_xml_node *node;
Check_Type(lang, T_STRING);
Data_Get_Struct(self, ruby_xml_node, node);
xmlNodeSetLang(node->node, (xmlChar*)StringValuePtr(lang));
return(Qtrue);
}
/*
* call-seq:
* node.last => node
*
* Obtain the last child node of this node, if any.
*/
VALUE
ruby_xml_node_last_get(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_ELEMENT_NODE:
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
case XML_DTD_NODE:
node = rxn->node->last;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = attr->last;
}
default:
node = NULL;
break;
}
if (node == NULL)
return(Qnil);
else
return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
}
/*
* call-seq:
* node.last? => (true|false)
*
* Determine whether this node has a last child node.
*/
VALUE
ruby_xml_node_last_q(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_ELEMENT_NODE:
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
case XML_DTD_NODE:
node = rxn->node->last;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = attr->last;
}
default:
node = NULL;
break;
}
if (node == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.line_num => num
*
* Obtain the line number (in the XML document) that this
* node was read from. If +default_line_numbers+ is set
* false (the default), this method returns zero.
*/
VALUE
ruby_xml_node_line_num(VALUE self) {
ruby_xml_node *rxn;
long line_num;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (!xmlLineNumbersDefaultValue)
rb_warn("Line numbers were not retained: use XML::Parser::default_line_numbers=true");
line_num = xmlGetLineNo(rxn->node);
if (line_num == -1)
return(Qnil);
else
return(INT2NUM((long)line_num));
}
/*
* call-seq:
* node.xlink? => (true|false)
*
* Determine whether this node is an xlink node.
*/
VALUE
ruby_xml_node_xlink_q(VALUE self) {
ruby_xml_node *node;
ruby_xml_document *doc;
xlinkType xlt;
Data_Get_Struct(self, ruby_xml_node, node);
Data_Get_Struct(node->xd, ruby_xml_document, doc);
xlt = xlinkIsLink(doc->doc, node->node);
if (xlt == XLINK_TYPE_NONE)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.xlink_type => num
*
* Obtain the type identifier for this xlink, if applicable.
* If this is not an xlink node (see +xlink?+), will return
* nil.
*/
VALUE
ruby_xml_node_xlink_type(VALUE self) {
ruby_xml_node *node;
ruby_xml_document *doc;
xlinkType xlt;
Data_Get_Struct(self, ruby_xml_node, node);
Data_Get_Struct(node->xd, ruby_xml_document, doc);
xlt = xlinkIsLink(doc->doc, node->node);
if (xlt == XLINK_TYPE_NONE)
return(Qnil);
else
return(INT2NUM(xlt));
}
/*
* call-seq:
* node.xlink_type_name => "string"
*
* Obtain the type name for this xlink, if applicable.
* If this is not an xlink node (see +xlink?+), will return
* nil.
*/
VALUE
ruby_xml_node_xlink_type_name(VALUE self) {
ruby_xml_node *node;
ruby_xml_document *doc;
xlinkType xlt;
Data_Get_Struct(self, ruby_xml_node, node);
Data_Get_Struct(node->xd, ruby_xml_document, doc);
xlt = xlinkIsLink(doc->doc, node->node);
switch(xlt) {
case XLINK_TYPE_NONE:
return(Qnil);
case XLINK_TYPE_SIMPLE:
return(rb_str_new2("simple"));
case XLINK_TYPE_EXTENDED:
return(rb_str_new2("extended"));
case XLINK_TYPE_EXTENDED_SET:
return(rb_str_new2("extended_set"));
default:
rb_fatal("Unknowng xlink type, %d", xlt);
}
}
static void
ruby_xml_node_mark(ruby_xml_node *rxn) {
if (rxn == NULL) return;
if (!NIL_P(rxn->xd)) rb_gc_mark(rxn->xd);
}
/*
* call-seq:
* node.name => "string"
*
* Obtain this node's name.
*/
VALUE
ruby_xml_node_name_get(VALUE self) {
ruby_xml_node *rxn;
const xmlChar *name;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
{
xmlDocPtr doc = (xmlDocPtr) rxn->node;
name = doc->URL;
break;
}
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
name = attr->name;
break;
}
case XML_NAMESPACE_DECL:
{
xmlNsPtr ns = (xmlNsPtr) rxn->node;
name = ns->prefix;
break;
}
default:
name = rxn->node->name;
break;
}
if (rxn->node->name == NULL)
return(Qnil);
else
return(rb_str_new2((const char*)name));
}
/*
* call-seq:
* node.name = "string"
*
* Set this node's name.
*/
VALUE
ruby_xml_node_name_set(VALUE self, VALUE name) {
ruby_xml_node *node;
Check_Type(name, T_STRING);
Data_Get_Struct(self, ruby_xml_node, node);
xmlNodeSetName(node->node, (xmlChar*)StringValuePtr(name));
return(Qtrue);
}
/*
* call-seq:
* node.namespace => [namespace, ..., namespace]
*
* Obtain an array of +XML::NS+ objects representing
* this node's xmlns attributes
*/
VALUE
ruby_xml_node_namespace_get(VALUE self) {
ruby_xml_node *node;
xmlNsPtr *nsList, *cur;
VALUE arr, ns;
Data_Get_Struct(self, ruby_xml_node, node);
if (node->node == NULL)
return(Qnil);
nsList = xmlGetNsList(node->node->doc, node->node);
if (nsList == NULL)
return(Qnil);
arr = rb_ary_new();
for (cur = nsList; *cur != NULL; cur++) {
ns = ruby_xml_ns_new2(cXMLNS, node->xd, *cur);
if (ns == Qnil)
continue;
else
rb_ary_push(arr, ns);
}
xmlFree(nsList);
return(arr);
}
/*
* call-seq:
* node.namespace_node => namespace.
*
* Obtain this node's namespace node.
*/
VALUE
ruby_xml_node_namespace_get_node(VALUE self) {
ruby_xml_node *node;
Data_Get_Struct(self, ruby_xml_node, node);
if (node->node->ns == NULL)
return(Qnil);
else
return(ruby_xml_ns_new2(cXMLNS, node->xd, node->node->ns));
}
// TODO namespace_set can take varargs (in fact, must if used
// with strings), but I cannot see how you can call
// that version, apart from with 'send'
//
// Would sure be nice to support foo.namespace['foo'] = 'bar'
// but maybe that's not practical...
/*
* call-seq:
* node.namespace = namespace
*
* Add the specified XML::NS object to this node's xmlns attributes.
*/
VALUE
ruby_xml_node_namespace_set(int argc, VALUE *argv, VALUE self) {
VALUE rns, rprefix;
ruby_xml_node *rxn;
ruby_xml_ns *rxns;
xmlNsPtr ns;
char *cp, *href;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (argc) {
case 1:
rns = argv[0];
if (TYPE(rns) == T_STRING) {
cp = strchr(StringValuePtr(rns), (int)':');
if (cp == NULL) {
rprefix = rns;
href = NULL;
} else {
rprefix = rb_str_new(StringValuePtr(rns), (int)((long)cp - (long)StringValuePtr(rns)));
href = &cp[1]; /* skip the : */
}
} else if (rb_obj_is_kind_of(rns, cXMLNS) == Qtrue) {
Data_Get_Struct(self, ruby_xml_ns, rxns);
xmlSetNs(rxn->node, rxns->ns);
return(rns);
} else
rb_raise(rb_eTypeError, "must pass a string or an XML::Ns object");
/* Fall through to next case because when argc == 1, we need to
* manually setup the additional args unless the arg passed is of
* cXMLNS type */
case 2:
/* Don't want this code run in the fall through case */
if (argc == 2) {
rprefix = argv[0];
href = StringValuePtr(argv[1]);
}
ns = xmlNewNs(rxn->node, (xmlChar*)href, (xmlChar*)StringValuePtr(rprefix));
if (ns == NULL)
rb_raise(eXMLNodeSetNamespace, "unable to set the namespace");
else
return(ruby_xml_ns_new2(cXMLNS, rxn->xd, ns));
break;
default:
rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
}
/* can't get here */
return(Qnil);
}
/*
* call-seq:
* node.namespace? => (true|false)
*
* Determine whether this node *is* (not has) a namespace
* node.
*/
VALUE
ruby_xml_node_namespace_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_NAMESPACE_DECL)
return(Qtrue);
else
return(Qfalse);
}
VALUE
ruby_xml_node_new(VALUE class, xmlNodePtr node) {
ruby_xml_node *rxn;
rxn = ALLOC(ruby_xml_node);
rxn->is_ptr = 0;
rxn->node = node;
rxn->xd = Qnil;
return(Data_Wrap_Struct(class, ruby_xml_node_mark,
ruby_xml_node_free, rxn));
}
VALUE
ruby_xml_node_new2(VALUE class, VALUE xd, xmlNodePtr node) {
ruby_xml_node *rxn;
rxn = ALLOC(ruby_xml_node);
rxn->is_ptr = 1;
rxn->node = node;
if (NIL_P(xd))
rxn->xd = Qnil;
else
rxn->xd = xd;
return(Data_Wrap_Struct(class, ruby_xml_node_mark,
ruby_xml_node_free, rxn));
}
/*
* call-seq:
* node.next => node
*
* Obtain the next sibling node, if any.
*/
VALUE
ruby_xml_node_next_get(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
node = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = (xmlNodePtr) attr->next;
break;
}
case XML_NAMESPACE_DECL:
{
xmlNsPtr ns = (xmlNsPtr) rxn->node;
node = (xmlNodePtr) ns->next;
break;
}
default:
node = rxn->node->next;
break;
}
if (node == NULL)
return(Qnil);
else
return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
}
/*
* call-seq:
* node.next? => (true|false)
*
* Determine whether this node has a next sibling.
*/
VALUE
ruby_xml_node_next_q(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
node = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = (xmlNodePtr) attr->next;
break;
}
case XML_NAMESPACE_DECL:
{
xmlNsPtr ns = (xmlNsPtr) rxn->node;
node = (xmlNodePtr) ns->next;
break;
}
default:
node = rxn->node->next;
break;
}
if (node == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.notation? => (true|false)
*
* Determine whether this is a notation node
*/
VALUE
ruby_xml_node_notation_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_NOTATION_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.ns? => (true|false)
*
* Determine whether this node is a namespace node.
*/
VALUE
ruby_xml_node_ns_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->ns == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.ns_def => namespace
*
* Obtain this node's default namespace.
*/
VALUE
ruby_xml_node_ns_def_get(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->nsDef == NULL)
return(Qnil);
else
return(ruby_xml_ns_new2(cXMLNS, rxn->xd, rxn->node->nsDef));
}
/*
* call-seq:
* node.ns_def? => (true|false)
*
* Obtain an array of +XML::NS+ objects representing
* this node's xmlns attributes
*/
VALUE
ruby_xml_node_ns_def_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->nsDef == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.parent => node
*
* Obtain this node's parent node, if any.
*/
VALUE
ruby_xml_node_parent_get(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
node = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = attr->parent;
}
case XML_ENTITY_DECL:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
node = NULL;
break;
default:
node = rxn->node->parent;
break;
}
if (node == NULL)
return(Qnil);
else
return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
}
/*
* call-seq:
* node.parent? => (true|false)
*
* Determine whether this node has a parent node.
*/
VALUE
ruby_xml_node_parent_q(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
node = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = attr->parent;
}
case XML_ENTITY_DECL:
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
node = NULL;
break;
default:
node = rxn->node->parent;
break;
}
if (node == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.path => path
*
* Obtain this node's path.
*/
VALUE
ruby_xml_node_path(VALUE self) {
ruby_xml_node *rxn;
xmlChar *path;
Data_Get_Struct(self, ruby_xml_node, rxn);
path = xmlGetNodePath(rxn->node);
if (path == NULL)
return(Qnil);
else
return(rb_str_new2((const char*)path));
}
/*
* call-seq:
* node.pi? => (true|false)
*
* Determine whether this is a processing instruction node.
*/
VALUE
ruby_xml_node_pi_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_PI_NODE)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.pointer => node_set
*
* Evaluates an XPointer expression relative to this node.
*/
VALUE
ruby_xml_node_pointer(VALUE self, VALUE xptr_str) {
return(ruby_xml_xpointer_point2(self, xptr_str));
}
/*
* call-seq:
* node.prev => node
*
* Obtain the previous sibling, if any.
*/
VALUE
ruby_xml_node_prev_get(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
case XML_NAMESPACE_DECL:
node = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = (xmlNodePtr) attr->next;
}
break;
default:
node = rxn->node->next;
break;
}
if (node == NULL)
return(Qnil);
else
return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
}
/*
* call-seq:
* node.prev? => (true|false)
*
* Determines whether this node has a previous sibling node.
*/
VALUE
ruby_xml_node_prev_q(VALUE self) {
ruby_xml_node *rxn;
xmlNodePtr node;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch (rxn->node->type) {
case XML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_HTML_DOCUMENT_NODE:
case XML_NAMESPACE_DECL:
node = NULL;
break;
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
node = (xmlNodePtr) attr->next;
}
break;
default:
node = rxn->node->next;
break;
}
if (node == NULL)
return(Qfalse);
else
return(Qtrue);
}
/*
* call-seq:
* node.property("name") => "string"
* node["name"] => "string"
*
* Obtain the named property.
*/
VALUE
ruby_xml_node_property_get(VALUE self, VALUE prop) {
ruby_xml_node *rxn;
xmlChar *p;
VALUE r;
Check_Type(prop, T_STRING);
Data_Get_Struct(self, ruby_xml_node, rxn);
p = xmlGetProp(rxn->node, (xmlChar*)StringValuePtr(prop));
if (p == NULL)
r = Qnil;
else {
r = rb_str_new2((const char*)p);
xmlFree(p);
}
return r;
}
/*
* call-seq:
* node["name"] = "string"
*
* Set the named property.
*/
VALUE
ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) {
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);
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);
}
rattr = ruby_xml_attr_new(cXMLAttr, node->xd, attr);
Data_Get_Struct(rattr, ruby_xml_attr, rxa);
rxa->is_ptr = 1;
return(rattr);
}
/*
* call-seq:
* node.properties => attributes
*
* Returns the +XML::Attr+ for this node.
*/
VALUE
ruby_xml_node_properties_get(VALUE self) {
ruby_xml_node *node;
xmlAttrPtr attr;
Data_Get_Struct(self, ruby_xml_node, node);
if (node->node->type == XML_ELEMENT_NODE) {
attr = node->node->properties;
return(ruby_xml_attr_new2(cXMLAttr, node->xd, attr));
} else {
return(Qnil);
}
}
/*
* call-seq:
* node.properties? => (true|false)
*
* Determine whether this node has properties
* (attributes).
*/
VALUE
ruby_xml_node_properties_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_ELEMENT_NODE && rxn->node->properties != NULL)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.search_href => namespace
*
* Search for a namespace by href.
*/
VALUE
ruby_xml_node_search_href(VALUE self, VALUE href) {
ruby_xml_document *doc;
ruby_xml_node *node;
Check_Type(href, T_STRING);
Data_Get_Struct(self, ruby_xml_node, node);
Data_Get_Struct(node->xd, ruby_xml_document, doc);
return(ruby_xml_ns_new2(cXMLNS, node->xd,
xmlSearchNsByHref(doc->doc, node->node,
(xmlChar*)StringValuePtr(href))));
}
/*
* call-seq:
* node.search_ns => namespace
*
* Search for a namespace by namespace.
*/
VALUE
ruby_xml_node_search_ns(VALUE self, VALUE ns) {
ruby_xml_document *doc;
ruby_xml_node *node;
Check_Type(ns, T_STRING);
Data_Get_Struct(self, ruby_xml_node, node);
Data_Get_Struct(node->xd, ruby_xml_document, doc);
return(ruby_xml_ns_new2(cXMLNS, node->xd,
xmlSearchNs(doc->doc, node->node,
(xmlChar*)StringValuePtr(ns))));
}
VALUE
ruby_xml_node_set_ptr(VALUE node, int is_ptr) {
ruby_xml_node *rxn;
Data_Get_Struct(node, ruby_xml_node, rxn);
rxn->is_ptr = is_ptr;
return(Qtrue);
}
/*
* call-seq:
* node.sibling(node) => node
*
* Add the specified node as a sibling of this node.
*/
VALUE
ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
ruby_xml_node *cnode, *pnode;
xmlNodePtr ret;
if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
rb_raise(rb_eTypeError, "Must pass an XML::Node object");
Data_Get_Struct(self, ruby_xml_node, pnode);
Data_Get_Struct(rnode, ruby_xml_node, cnode);
ret = xmlAddSibling(pnode->node, cnode->node);
if (ret == NULL)
rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
cnode->is_ptr = 1;
return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
}
/*
* call-seq:
* node.space_preserve => (true|false)
*
* Determine whether this node preserves whitespace.
*/
VALUE
ruby_xml_node_space_preserve_get(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
return(INT2NUM(xmlNodeGetSpacePreserve(rxn->node)));
}
/*
* call-seq:
* node.space_preserve = true|false
*
* Control whether this node preserves whitespace.
*/
VALUE
ruby_xml_node_space_preserve_set(VALUE self, VALUE bool) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (TYPE(bool) == T_FALSE)
xmlNodeSetSpacePreserve(rxn->node, 1);
else
xmlNodeSetSpacePreserve(rxn->node, 0);
return(Qnil);
}
/*
* call-seq:
* node.text? => (true|false)
*
* Determine whether this node has text.
*/
VALUE
ruby_xml_node_text_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node == NULL)
return(Qnil);
return((xmlNodeIsText(rxn->node) == 1) ? Qtrue : Qfalse);
}
/*
* call-seq:
* node.to_s => "string"
*
* Coerce this node to a string representation of
* it's XML.
*/
VALUE
ruby_xml_node_to_s(VALUE self) {
ruby_xml_node *rxn;
xmlBufferPtr buf;
VALUE result;
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;
}
/*
* call-seq:
* node.type => num
*
* Obtain this node's type identifier.
*/
VALUE
ruby_xml_node_type(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
return(INT2NUM(rxn->node->type));
}
/*
* call-seq:
* node.type_name => num
*
* Obtain this node's type name.
*/
VALUE
ruby_xml_node_type_name(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
switch(rxn->node->type) {
case XML_ELEMENT_NODE:
return(rb_str_new2("element"));
case XML_ATTRIBUTE_NODE:
return(rb_str_new2("attribute"));
case XML_TEXT_NODE:
return(rb_str_new2("text"));
case XML_CDATA_SECTION_NODE:
return(rb_str_new2("cdata"));
case XML_ENTITY_REF_NODE:
return(rb_str_new2("entity_ref"));
case XML_ENTITY_NODE:
return(rb_str_new2("entity"));
case XML_PI_NODE:
return(rb_str_new2("pi"));
case XML_COMMENT_NODE:
return(rb_str_new2("comment"));
case XML_DOCUMENT_NODE:
return(rb_str_new2("document_xml"));
case XML_DOCUMENT_TYPE_NODE:
return(rb_str_new2("doctype"));
case XML_DOCUMENT_FRAG_NODE:
return(rb_str_new2("fragment"));
case XML_NOTATION_NODE:
return(rb_str_new2("notation"));
case XML_HTML_DOCUMENT_NODE:
return(rb_str_new2("document_html"));
case XML_DTD_NODE:
return(rb_str_new2("dtd"));
case XML_ELEMENT_DECL:
return(rb_str_new2("elem_decl"));
case XML_ATTRIBUTE_DECL:
return(rb_str_new2("attribute_decl"));
case XML_ENTITY_DECL:
return(rb_str_new2("entity_decl"));
case XML_NAMESPACE_DECL:
return(rb_str_new2("namespace"));
case XML_XINCLUDE_START:
return(rb_str_new2("xinclude_start"));
case XML_XINCLUDE_END:
return(rb_str_new2("xinclude_end"));
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
return(rb_str_new2("document_docbook"));
#endif
default:
rb_raise(eXMLNodeUnknownType, "Unknown node type: %n", rxn->node->type);
return(Qfalse);
}
}
/*
* call-seq:
* node.xinclude_end? => num
*
* Determine whether this node is an xinclude end node.
*/
VALUE
ruby_xml_node_xinclude_end_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_XINCLUDE_END)
return(Qtrue);
else
return(Qfalse);
}
/*
* call-seq:
* node.xinclude_start? => num
*
* Determine whether this node is an xinclude start node.
*/
VALUE
ruby_xml_node_xinclude_start_q(VALUE self) {
ruby_xml_node *rxn;
Data_Get_Struct(self, ruby_xml_node, rxn);
if (rxn->node->type == XML_XINCLUDE_START)
return(Qtrue);
else
return(Qfalse);
}
// TODO my gut tells me this is where our sigseg etc. problems start...
/*
* call-seq:
* node.copy => node
*
* Create a copy of this node.
*/
VALUE
ruby_xml_node_copy(VALUE self, VALUE deep) { /* MUFF */
ruby_xml_node *rxn, *n_rxn;
VALUE n_node;
Data_Get_Struct(self, ruby_xml_node, rxn);
n_node = ruby_xml_node_new(cXMLNode, NULL); // class??
Data_Get_Struct(n_node, ruby_xml_node, n_rxn);
n_rxn->node = xmlCopyNode( rxn->node, ((deep==Qnil)||(deep==Qfalse))?0:1 );
if (rxn->node == NULL)
return(Qnil);
return n_node;
}
// Rdoc needs to know
#ifdef RDOC_NEVER_DEFINED
mXML = rb_define_module("XML");
#endif
void
ruby_init_xml_node(void) {
cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
eXMLNodeSetNamespace = rb_define_class_under(cXMLNode, "SetNamespace", rb_eException);
eXMLNodeFailedModify = rb_define_class_under(cXMLNode, "FailedModify", rb_eException);
eXMLNodeUnknownType = rb_define_class_under(cXMLNode, "UnknownType", rb_eException);
rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
rb_define_singleton_method(cXMLNode, "new", ruby_xml_node_initialize, -1);
rb_define_method(cXMLNode, "<<", ruby_xml_node_content_add, 1);
rb_define_method(cXMLNode, "[]", ruby_xml_node_property_get, 1);
rb_define_method(cXMLNode, "[]=", ruby_xml_node_property_set, 2);
rb_define_method(cXMLNode, "attribute?", ruby_xml_node_attribute_q, 0);
rb_define_method(cXMLNode, "attribute_decl?", ruby_xml_node_attribute_decl_q, 0);
rb_define_method(cXMLNode, "base", ruby_xml_node_base_get, 0);
rb_define_method(cXMLNode, "base=", ruby_xml_node_base_set, 1);
rb_define_method(cXMLNode, "blank?", ruby_xml_node_empty_q, 0);
rb_define_method(cXMLNode, "cdata?", ruby_xml_node_cdata_q, 0);
rb_define_method(cXMLNode, "comment?", ruby_xml_node_comment_q, 0);
rb_define_method(cXMLNode, "copy", ruby_xml_node_copy, 1);
rb_define_method(cXMLNode, "child", ruby_xml_node_child_get, 0);
rb_define_method(cXMLNode, "child?", ruby_xml_node_child_q, 0);
rb_define_method(cXMLNode, "child=", ruby_xml_node_child_set, 1);
rb_define_method(cXMLNode, "children", ruby_xml_node_child_get, 0);
rb_define_method(cXMLNode, "children?", ruby_xml_node_child_q, 0);
rb_define_method(cXMLNode, "content", ruby_xml_node_content_get, 0);
rb_define_method(cXMLNode, "content=", ruby_xml_node_content_set, 1);
rb_define_method(cXMLNode, "content_stripped", ruby_xml_node_content_stripped_get, 0);
rb_define_method(cXMLNode, "doc", ruby_xml_node_doc, 0);
rb_define_method(cXMLNode, "docbook_doc?", ruby_xml_node_docbook_doc_q, 0);
rb_define_method(cXMLNode, "doctype?", ruby_xml_node_doctype_q, 0);
rb_define_method(cXMLNode, "document?", ruby_xml_node_document_q, 0);
rb_define_method(cXMLNode, "dtd?", ruby_xml_node_dtd_q, 0);
rb_define_method(cXMLNode, "dump", ruby_xml_node_dump, 0);
rb_define_method(cXMLNode, "debug_dump", ruby_xml_node_debug_dump, 0);
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, "find", ruby_xml_node_find, -1);
rb_define_method(cXMLNode, "fragment?", ruby_xml_node_fragment_q, 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);
rb_define_method(cXMLNode, "line_num", ruby_xml_node_line_num, 0);
rb_define_method(cXMLNode, "name", ruby_xml_node_name_get, 0);
rb_define_method(cXMLNode, "name=", ruby_xml_node_name_set, 1);
rb_define_method(cXMLNode, "namespace", ruby_xml_node_namespace_get, 0);
rb_define_method(cXMLNode, "namespace_node", ruby_xml_node_namespace_get_node, 0);
rb_define_method(cXMLNode, "namespace?", ruby_xml_node_namespace_q, 0);
rb_define_method(cXMLNode, "namespace=", ruby_xml_node_namespace_set, -1);
rb_define_method(cXMLNode, "next", ruby_xml_node_next_get, 0);
rb_define_method(cXMLNode, "next?", ruby_xml_node_next_q, 0);
rb_define_method(cXMLNode, "node_type", ruby_xml_node_type, 0);
rb_define_method(cXMLNode, "node_type_name", ruby_xml_node_type_name, 0);
rb_define_method(cXMLNode, "notation?", ruby_xml_node_notation_q, 0);
rb_define_method(cXMLNode, "ns", ruby_xml_node_namespace_get, 0);
rb_define_method(cXMLNode, "ns?", ruby_xml_node_ns_q, 0);
rb_define_method(cXMLNode, "ns_def", ruby_xml_node_ns_def_get, 0);
rb_define_method(cXMLNode, "ns_def?", ruby_xml_node_ns_def_q, 0);
rb_define_method(cXMLNode, "parent", ruby_xml_node_parent_get, 0);
rb_define_method(cXMLNode, "parent?", ruby_xml_node_parent_q, 0);
rb_define_method(cXMLNode, "path", ruby_xml_node_path, 0);
rb_define_method(cXMLNode, "pi?", ruby_xml_node_pi_q, 0);
rb_define_method(cXMLNode, "pointer", ruby_xml_node_pointer, 1);
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, "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);
rb_define_method(cXMLNode, "text?", ruby_xml_node_text_q, 0);
rb_define_method(cXMLNode, "to_s", ruby_xml_node_to_s, 0);
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);
}