/* $Id: ruby_xml_node.c,v 1.41 2003/02/06 09:27:48 sean Exp $ */ /* Please see the LICENSE file for copyright and distribution information */ #include "libxml.h" #include "ruby_xml_node.h" VALUE cXMLNode; VALUE eXMLNodeUnknownType; VALUE eXMLNodeFailedModify; 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); } 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); } 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); return(rb_str_new2(xmlNodeGetBase(rxn->node->doc, rxn->node))); } 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, STR2CSTR(uri)); return(Qtrue); } 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); } 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); } VALUE ruby_xml_node_content_add(VALUE self, VALUE obj) { ruby_xml_node *node; Data_Get_Struct(self, ruby_xml_node, node); if (TYPE(obj) == T_STRING) { xmlNodeAddContent(node->node, STR2CSTR(obj)); return(obj); } else if (rb_obj_is_kind_of(obj, cXMLNode)) { return(ruby_xml_node_child_set(self, obj)); } else { rb_raise(rb_eTypeError, "invalid argumnt: must be string or XML::Node"); } } 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(rxn->node->content)); } } 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, STR2CSTR(content)); return(Qtrue); } 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(xmlNodeGetContent(rxn->node))); } 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)); } 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); } 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)); } 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); } 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 } 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); } 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); } 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); } 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); } 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); } 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); } 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); } 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); } 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); } 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); } VALUE ruby_xml_node_find(VALUE self, VALUE xpath_str) { return(ruby_xml_xpath_find2(self, xpath_str)); } 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); } free(rxn); } 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); } 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: if (TYPE(str) == T_STRING) str = argv[1]; else { str = rb_obj_as_string(argv[1]); if (NIL_P(str)) Check_Type(str, T_STRING); } 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, STR2CSTR(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); } VALUE ruby_xml_node_lang_get(VALUE self) { ruby_xml_node *rxn; char *lang; Data_Get_Struct(self, ruby_xml_node, rxn); lang = xmlNodeGetLang(rxn->node); if (lang == NULL) return(Qnil); else return(rb_str_new2(lang)); } 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, STR2CSTR(lang)); return(Qtrue); } 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)); } 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); } 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 being kept track of: use XML::Parser::default_line_numbers=true"); line_num = xmlGetLineNo(rxn->node); if (line_num == -1) return(Qnil); else return(INT2NUM((long)line_num)); } 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); } 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)); } 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); } 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(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, STR2CSTR(name)); return(Qtrue); } 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)); } 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)); } 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); } 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); } VALUE ruby_xml_node_ns_get(VALUE self) { ruby_xml_node *rxn; Data_Get_Struct(self, ruby_xml_node, rxn); if (rxn->node->ns == NULL) return(Qnil); else return(ruby_xml_ns_new2(cXMLNS, rxn->xd, rxn->node->ns)); } 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); } 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)); } 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); } 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)); } 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); } VALUE ruby_xml_node_path(VALUE self) { ruby_xml_node *rxn; char *path; Data_Get_Struct(self, ruby_xml_node, rxn); path = xmlGetNodePath(rxn->node); if (path == NULL) return(Qnil); else return(rb_str_new2(path)); } 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); } 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)); } 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); } VALUE ruby_xml_node_property_get(VALUE self, VALUE prop) { ruby_xml_node *rxn; char *p; Check_Type(prop, T_STRING); Data_Get_Struct(self, ruby_xml_node, rxn); p = xmlGetProp(rxn->node, STR2CSTR(prop)); if (p == NULL) return(Qnil); else return(rb_str_new2(p)); } VALUE ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) { ruby_xml_node *node; xmlAttrPtr attr; Check_Type(key, T_STRING); Check_Type(val, T_STRING); Data_Get_Struct(self, ruby_xml_node, node); attr = xmlNewProp(node->node, STR2CSTR(key), STR2CSTR(val)); if (attr == NULL) return(Qnil); else return(ruby_xml_attr_new(cXMLAttr, node->xd, attr)); } 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_new(cXMLAttr, node->xd, attr)); } else { return(Qnil); } } 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); } 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, STR2CSTR(href)))); } 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); } 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)); } 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))); } 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); } 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); } VALUE ruby_xml_node_to_s(VALUE self) { ruby_xml_node *rxn; Data_Get_Struct(self, ruby_xml_node, rxn); if (rxn->node->children != NULL && rxn->node->children->content != NULL) { return(rb_str_new2(rxn->node->children->content)); } else { return(Qnil); } } VALUE ruby_xml_node_type(VALUE self) { ruby_xml_node *rxn; Data_Get_Struct(self, ruby_xml_node, rxn); return(INT2NUM(rxn->node->type)); } 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); } } 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); } 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); } void ruby_init_xml_node(void) { cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject); eXMLNodeUnknownType = rb_define_class_under(cXMLNode, "UnknownType", rb_eException); eXMLNodeFailedModify = rb_define_class_under(cXMLNode, "FailedModify", 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, "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_q, 0); 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_ns_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, "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_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); }