static void end_element_ns_callback(void *ctx, const xmlChar *xlocalname, const xmlChar *xprefix, const xmlChar *xURI) { VALUE handler = (VALUE) ctx; if (handler == Qnil) return; /* Call end element for old-times sake */ if (rb_respond_to(handler, cbidOnEndElement)) { VALUE name; if (xprefix) { name = rxml_new_cstr(xprefix, NULL); rb_str_cat2(name, ":"); rb_str_cat2(name, xlocalname); } else { name = rxml_new_cstr(xlocalname, NULL); } rb_funcall(handler, cbidOnEndElement, 1, name); } rb_funcall(handler, cbidOnEndElementNs, 3, rxml_new_cstr(xlocalname, NULL), xprefix ? rxml_new_cstr(xprefix, NULL) : Qnil, xURI ? rxml_new_cstr(xURI, NULL) : Qnil); }
static void processing_instruction_callback(void *ctx, const char *target, const char *data) { VALUE handler = (VALUE) ctx; if (handler != Qnil) { VALUE rtarget = target ? rxml_new_cstr(target, NULL) : Qnil; VALUE rdata = data ? rxml_new_cstr(data, NULL) : Qnil; rb_funcall(handler, cbidOnProcessingInstruction, 2, rtarget, rdata); } }
static void external_subset_callback(void *ctx, const char *name, const char *extid, const char *sysid) { VALUE handler = (VALUE) ctx; if (handler != Qnil) { VALUE rname = name ? rxml_new_cstr(name, NULL) : Qnil; VALUE rextid = extid ? rxml_new_cstr(extid, NULL) : Qnil; VALUE rsysid = sysid ? rxml_new_cstr(sysid, NULL) : Qnil; rb_funcall(handler, cbidOnExternalSubset, 3, rname, rextid, rsysid); } }
static VALUE rxml_node_to_s(int argc, VALUE *argv, VALUE self) { VALUE result = Qnil; VALUE options = Qnil; xmlNodePtr xnode; xmlCharEncodingHandlerPtr encodingHandler; xmlOutputBufferPtr output; int level = 0; int indent = 1; const char *xencoding = "UTF-8"; rb_scan_args(argc, argv, "01", &options); if (!NIL_P(options)) { VALUE rencoding, rindent, rlevel; Check_Type(options, T_HASH); rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding"))); rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent"))); rlevel = rb_hash_aref(options, ID2SYM(rb_intern("level"))); if (rindent == Qfalse) indent = 0; if (rlevel != Qnil) level = NUM2INT(rlevel); if (rencoding != Qnil) { xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding)); if (!xencoding) rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding)); } } encodingHandler = xmlFindCharEncodingHandler(xencoding); output = xmlAllocOutputBuffer(encodingHandler); xnode = rxml_get_xnode(self); xmlNodeDumpOutput(output, xnode->doc, xnode, level, indent, xencoding); xmlOutputBufferFlush(output); if (output->conv) result = rxml_new_cstr((const char*) output->conv->content, xencoding); else result = rxml_new_cstr((const char*) output->buffer->content, xencoding); xmlOutputBufferClose(output); return result; }
static void start_element_ns_callback(void *ctx, const xmlChar *xlocalname, const xmlChar *xprefix, const xmlChar *xURI, int nb_namespaces, const xmlChar **xnamespaces, int nb_attributes, int nb_defaulted, const xmlChar **xattributes) { VALUE handler = (VALUE) ctx; VALUE attributes = rb_hash_new(); VALUE namespaces = rb_hash_new(); if (handler == Qnil) return; if (xattributes) { /* Each attribute is an array of [localname, prefix, URI, value, end] */ int i; for (i = 0;i < nb_attributes * 5; i+=5) { VALUE attrName = rxml_new_cstr(xattributes[i+0], NULL); VALUE attrValue = rxml_new_cstr_len(xattributes[i+3], xattributes[i+4] - xattributes[i+3], NULL); rb_hash_aset(attributes, attrName, attrValue); } } if (xnamespaces) { int i; for (i = 0;i < nb_namespaces * 2; i+=2) { VALUE nsPrefix = xnamespaces[i+0] ? rxml_new_cstr(xnamespaces[i+0], NULL) : Qnil; VALUE nsURI = xnamespaces[i+1] ? rxml_new_cstr(xnamespaces[i+1], NULL) : Qnil; rb_hash_aset(namespaces, nsPrefix, nsURI); } } /* Call start element for old-times sake */ if (rb_respond_to(handler, cbidOnStartElement)) { VALUE name; if (xprefix) { name = rxml_new_cstr(xprefix, NULL); rb_str_cat2(name, ":"); rb_str_cat2(name, xlocalname); } else { name = rxml_new_cstr(xlocalname, NULL); } rb_funcall(handler, cbidOnStartElement, 2, name, attributes); } rb_funcall(handler, cbidOnStartElementNs, 5, rxml_new_cstr(xlocalname, NULL), attributes, xprefix ? rxml_new_cstr(xprefix, NULL) : Qnil, xURI ? rxml_new_cstr(xURI, NULL) : Qnil, namespaces); }
/* 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_new_cstr(xns->prefix, xctxt->doc->encoding); VALUE uri = rxml_new_cstr(xns->href, xctxt->doc->encoding); rxml_xpath_context_register_namespace(self, prefix, uri); } xns = xns->next; } xmlFree(xnsArr); } return self; }
/* * call-seq: * reader.namespace_uri -> URI * * Determine the namespace URI of the node. */ static VALUE rxml_reader_namespace_uri(VALUE self) { xmlTextReaderPtr xReader = rxml_text_reader_get(self); const xmlChar *result = xmlTextReaderConstNamespaceUri(xReader); const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader); return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding)); }
/* * call-seq: * reader.xml_version -> version * * Determine the XML version of the document being read. */ static VALUE rxml_reader_xml_version(VALUE self) { xmlTextReaderPtr xReader = rxml_text_reader_get(self); const xmlChar *result = xmlTextReaderConstXmlVersion(xReader); const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader); return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding)); }
static void comment_callback(void *ctx, const char *msg) { VALUE handler = (VALUE) ctx; if (handler != Qnil) { rb_funcall(handler, cbidOnComment,1,rxml_new_cstr(msg, NULL)); } }
static void reference_callback(void *ctx, const char *name) { VALUE handler = (VALUE) ctx; if (handler != Qnil) { rb_funcall(handler, cbidOnReference,1,rxml_new_cstr(name, NULL)); } }
/* * call-seq: * Input.encoding_to_s(Input::ENCODING) -> "encoding" * * Converts an encoding constant defined on the XML::Encoding * class to its text representation. */ static VALUE rxml_encoding_to_s(VALUE klass, VALUE encoding) { const char* xencoding = xmlGetCharEncodingName(NUM2INT(encoding)); if (!xencoding) return Qnil; else return rxml_new_cstr(xencoding, xencoding); }
/* * call-seq: * dtd.uri -> "string" * * Obtain this dtd's URI (for a SYSTEM or PUBLIC DTD). */ static VALUE rxml_dtd_uri_get(VALUE self) { xmlDtdPtr xdtd; Data_Get_Struct(self, xmlDtd, xdtd); if (xdtd->SystemID == NULL) return (Qnil); else return (rxml_new_cstr( xdtd->SystemID, NULL)); }
/* * call-seq: * attr_decl.name -> "name" * * Obtain this attribute declaration's name. */ static VALUE rxml_attr_decl_name_get(VALUE self) { xmlAttributePtr xattr; Data_Get_Struct(self, xmlAttribute, xattr); if (xattr->name == NULL) return Qnil; else return rxml_new_cstr((const char*) xattr->name, xattr->doc->encoding); }
/* * call-seq: * document.version -> "version" * * Obtain the XML version specified by this document. */ static VALUE rxml_document_version_get(VALUE self) { xmlDocPtr xdoc; Data_Get_Struct(self, xmlDoc, xdoc); if (xdoc->version == NULL) return (Qnil); else return (rxml_new_cstr((const char*) xdoc->version, NULL)); }
/* * call-seq: * xpath_object.string -> String * * Returns the original XPath expression as a string. */ static VALUE rxml_xpath_object_string(VALUE self) { rxml_xpath_object *rxpop; Data_Get_Struct(self, rxml_xpath_object, rxpop); if (rxpop->xpop->stringval == NULL) return Qnil; return rxml_new_cstr((const char*) rxpop->xpop->stringval, rxpop->xdoc->encoding); }
/* * call-seq: * dtd.external_id -> "string" * * Obtain this dtd's external identifer (for a PUBLIC DTD). */ static VALUE rxml_dtd_external_id_get(VALUE self) { xmlDtdPtr xdtd; Data_Get_Struct(self, xmlDtd, xdtd); if (xdtd->ExternalID == NULL) return (Qnil); else return (rxml_new_cstr( xdtd->ExternalID, NULL)); }
/* * call-seq: * attr_decl.value -> "value" * * Obtain the default value of this attribute declaration. */ VALUE rxml_attr_decl_value_get(VALUE self) { xmlAttributePtr xattr; Data_Get_Struct(self, xmlAttribute, xattr); if (xattr->defaultValue) return rxml_new_cstr((const char *)xattr->defaultValue, NULL); else return Qnil; }
/* * call-seq: * dtd.name -> "string" * * Obtain this dtd's name. */ static VALUE rxml_dtd_name_get(VALUE self) { xmlDtdPtr xdtd; Data_Get_Struct(self, xmlDtd, xdtd); if (xdtd->name == NULL) return (Qnil); else return (rxml_new_cstr( xdtd->name, NULL)); }
/* * call-seq: * node.path -> path * * Obtain this node's path. */ static VALUE rxml_node_path(VALUE self) { xmlNodePtr xnode; xmlChar *path; xnode = rxml_get_xnode(self); path = xmlGetNodePath(xnode); if (path == NULL) return (Qnil); else return (rxml_new_cstr((const char*) path, NULL)); }
/* * 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. */ static VALUE rxml_node_xlink_type_name(VALUE self) { xmlNodePtr xnode; xlinkType xlt; xnode = rxml_get_xnode(self); xlt = xlinkIsLink(xnode->doc, xnode); switch (xlt) { case XLINK_TYPE_NONE: return (Qnil); case XLINK_TYPE_SIMPLE: return (rxml_new_cstr("simple", NULL)); case XLINK_TYPE_EXTENDED: return (rxml_new_cstr("extended", NULL)); case XLINK_TYPE_EXTENDED_SET: return (rxml_new_cstr("extended_set", NULL)); default: rb_fatal("Unknowng xlink type, %d", xlt); } }
/* * call-seq: * reader.lookup_namespace(prefix) -> value * * Resolve a namespace prefix in the scope of the current element. * To return the default namespace, specify nil as +prefix+. */ static VALUE rxml_reader_lookup_namespace(VALUE self, VALUE prefix) { VALUE result = Qnil; xmlTextReaderPtr xReader = rxml_text_reader_get(self); const xmlChar *xnamespace = xmlTextReaderLookupNamespace(xReader, (const xmlChar *) StringValueCStr(prefix)); const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader); if (xnamespace) { result = rxml_new_cstr((const char*)xnamespace, (const char*)xencoding); xmlFree((void *)xnamespace); } return result; }
/* * call-seq: * node.content -> "string" * * Obtain this node's content as a string. */ static VALUE rxml_node_content_get(VALUE self) { xmlNodePtr xnode; xmlChar *content; VALUE result = Qnil; xnode = rxml_get_xnode(self); content = xmlNodeGetContent(xnode); if (content) { result = rxml_new_cstr((const char *) content, NULL); xmlFree(content); } return result; }
/* * call-seq: * reader.read_string -> string * * Read the contents of an element or a text node as a string. * * Return a string containing the contents of the Element or Text node, or nil * if the reader is positioned on any other type of node. */ static VALUE rxml_reader_read_string(VALUE self) { VALUE result = Qnil; xmlTextReaderPtr xReader = rxml_text_reader_get(self); xmlChar *xml = xmlTextReaderReadString(xReader); if (xml) { const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader); result = rxml_new_cstr((const char*) xml, xencoding); xmlFree(xml); } return result; }
/* * call-seq: * node.lang -> "string" * * Obtain the language set for this node, if any. * This is set in XML via the xml:lang attribute. */ static VALUE rxml_node_lang_get(VALUE self) { xmlNodePtr xnode; xmlChar *lang; VALUE result = Qnil; xnode = rxml_get_xnode(self); lang = xmlNodeGetLang(xnode); if (lang) { result = rxml_new_cstr((const char*) lang, NULL); xmlFree(lang); } return (result); }
/* * 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), (long) ((intptr_t) cp - (intptr_t)StringValuePtr(nslist))); ruri = rxml_new_cstr((const xmlChar*)&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; }
/* * call-seq: * node.base_uri -> "uri" * * Obtain this node's base URI. */ static VALUE rxml_node_base_uri_get(VALUE self) { xmlNodePtr xnode; xmlChar* base_uri; VALUE result = Qnil; xnode = rxml_get_xnode(self); if (xnode->doc == NULL) return (result); base_uri = xmlNodeGetBase(xnode->doc, xnode); if (base_uri) { result = rxml_new_cstr((const char*) base_uri, NULL); xmlFree(base_uri); } return (result); }
/* * call-seq: * node.name -> "string" * * Obtain this node's name. */ static VALUE rxml_node_name_get(VALUE self) { xmlNodePtr xnode; const xmlChar *name; xnode = rxml_get_xnode(self); switch (xnode->type) { case XML_DOCUMENT_NODE: #ifdef LIBXML_DOCB_ENABLED case XML_DOCB_DOCUMENT_NODE: #endif case XML_HTML_DOCUMENT_NODE: { xmlDocPtr doc = (xmlDocPtr) xnode; name = doc->URL; break; } case XML_ATTRIBUTE_NODE: { xmlAttrPtr attr = (xmlAttrPtr) xnode; name = attr->name; break; } case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) xnode; name = ns->prefix; break; } default: name = xnode->name; break; } if (xnode->name == NULL) return (Qnil); else return (rxml_new_cstr((const char*) name, NULL)); }
VALUE rxml_xpath_to_value(xmlXPathContextPtr xctxt, xmlXPathObjectPtr xobject) { VALUE result; int type; if (xobject == NULL) { /* xmlLastError is different than xctxt->lastError. Use xmlLastError since it has the message set while xctxt->lastError does not. */ xmlErrorPtr xerror = xmlGetLastError(); rxml_raise(xerror); } switch (type = xobject->type) { case XPATH_NODESET: result = rxml_xpath_object_wrap(xctxt->doc, xobject); break; case XPATH_BOOLEAN: result = (xobject->boolval != 0) ? Qtrue : Qfalse; xmlXPathFreeObject(xobject); break; case XPATH_NUMBER: result = rb_float_new(xobject->floatval); xmlXPathFreeObject(xobject); break; case XPATH_STRING: result = rxml_new_cstr(xobject->stringval, xctxt->doc->encoding); xmlXPathFreeObject(xobject); break; default: xmlXPathFreeObject(xobject); rb_raise(rb_eTypeError, "can't convert XPath object of type %d to Ruby value", type ); } return result; }
/* * call-seq: * reader[key] -> value * * Provide the value of the attribute with the specified index (if +key+ is an * integer) or with the specified name (if +key+ is a string) relative to the * containing element, as a string. */ static VALUE rxml_reader_attribute(VALUE self, VALUE key) { VALUE result = Qnil; xmlChar *xattr; xmlTextReaderPtr xReader = rxml_text_reader_get(self); const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader); if (TYPE(key) == T_FIXNUM) { xattr = xmlTextReaderGetAttributeNo(xReader, FIX2INT(key)); } else { xattr = xmlTextReaderGetAttribute(xReader, (const xmlChar *) StringValueCStr(key)); } if (xattr) { result = rxml_new_cstr(xattr, xencoding); xmlFree(xattr); } return result; }
/* * call-seq: * document.to_s -> "string" * document.to_s(:indent => true, :encoding => XML::Encoding::UTF_8) -> "string" * * Converts a document, and all of its children, to a string representation. * You may provide an optional hash table to control how the string is * generated. Valid options are: * * :indent - Specifies if the string should be indented. The default value * is true. Note that indentation is only added if both :indent is * true and XML.indent_tree_output is true. If :indent is set to false, * then both indentation and line feeds are removed from the result. * * :encoding - Specifies the output encoding of the string. It * defaults to XML::Encoding::UTF8. To change it, use one of the * XML::Encoding encoding constants. */ static VALUE rxml_document_to_s(int argc, VALUE *argv, VALUE self) { VALUE result; VALUE options = Qnil; xmlDocPtr xdoc; int indent = 1; const char *xencoding = "UTF-8"; xmlChar *buffer; int length; rb_scan_args(argc, argv, "01", &options); if (!NIL_P(options)) { VALUE rencoding, rindent; Check_Type(options, T_HASH); rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding"))); rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent"))); if (rindent == Qfalse) indent = 0; if (rencoding != Qnil) { xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding)); if (!xencoding) rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding)); } } Data_Get_Struct(self, xmlDoc, xdoc); xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, xencoding, indent); result = rxml_new_cstr((const char*) buffer, xencoding); xmlFree(buffer); return result; }