/* call-seq: * XML::Parser::Context.io(io) -> XML::Parser::Context * * Creates a new parser context based on the specified io object. * * Parameters: * * io - A ruby IO object. */ static VALUE rxml_parser_context_io(VALUE klass, VALUE io) { xmlParserCtxtPtr ctxt; xmlParserInputBufferPtr input; xmlParserInputPtr stream; input = xmlParserInputBufferCreateIO((xmlInputReadCallback) rxml_read_callback, NULL, (void*)io, XML_CHAR_ENCODING_NONE); ctxt = xmlNewParserCtxt(); if (!ctxt) { xmlFreeParserInputBuffer(input); rxml_raise(&xmlLastError); } stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); if (!stream) { xmlFreeParserInputBuffer(input); xmlFreeParserCtxt(ctxt); rxml_raise(&xmlLastError); } inputPush(ctxt, stream); return rxml_parser_context_wrap(ctxt); }
/* * underlying for child_set and child_add, difference being * former raises on implicit copy, latter does not. */ static VALUE rxml_node_child_set_aux(VALUE self, VALUE rnode) { xmlNodePtr pnode, chld, ret; if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse) rb_raise(rb_eTypeError, "Must pass an XML::Node object"); Data_Get_Struct(self, xmlNode, pnode); Data_Get_Struct(rnode, xmlNode, chld); if (chld->parent != NULL || chld->doc != NULL) rb_raise( rb_eRuntimeError, "Cannot move a node from one document to another with child= or <<. First copy the node before moving it."); ret = xmlAddChild(pnode, chld); if (ret == NULL) { rxml_raise(&xmlLastError); } else if (ret == chld) { /* child was added whole to parent and we need to return it as a new object */ return rxml_node_wrap(cXMLNode, chld); } /* else */ /* If it was a text node, then ret should be parent->last, so we will just return ret. */ return rxml_node_wrap(cXMLNode, ret); }
/* * call-seq: * document.validate(dtd) -> (true|false) * * Validate this document against the specified XML::DTD. */ static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd) { VALUE error = Qnil; xmlValidCtxt ctxt; xmlDocPtr xdoc; xmlDtdPtr xdtd; Data_Get_Struct(self, xmlDoc, xdoc); Data_Get_Struct(dtd, xmlDtd, xdtd); ctxt.userData = &error; ctxt.error = (xmlValidityErrorFunc) LibXML_validity_error; ctxt.warning = (xmlValidityWarningFunc) LibXML_validity_warning; ctxt.nodeNr = 0; ctxt.nodeTab = NULL; ctxt.vstateNr = 0; ctxt.vstateTab = NULL; if (xmlValidateDtd(&ctxt, xdoc, xdtd)) { return (Qtrue); } else { rxml_raise(&xmlLastError); return Qfalse; } }
/* * call-seq: * parser.parse -> (true|false) * * Parse the input XML, generating callbacks to the object * registered via the +callbacks+ attributesibute. */ static VALUE rxml_sax_parser_parse(VALUE self) { int status; VALUE context = rb_ivar_get(self, CONTEXT_ATTR); xmlParserCtxtPtr ctxt; Data_Get_Struct(context, xmlParserCtxt, ctxt); ctxt->sax2 = 1; ctxt->userData = (void*)rb_ivar_get(self, CALLBACKS_ATTR); if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) xmlFree(ctxt->sax); ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(rxml_sax_handler)); if (ctxt->sax == NULL) rb_fatal("Not enough memory."); memcpy(ctxt->sax, &rxml_sax_handler, sizeof(rxml_sax_handler)); status = xmlParseDocument(ctxt); /* Now check the parsing result*/ if (status == -1 || !ctxt->wellFormed) { if (ctxt->myDoc) xmlFreeDoc(ctxt->myDoc); rxml_raise(&ctxt->lastError); } return Qtrue; }
/* * call-seq: * XML::Node.new_pi(name, content = nil) -> XML::Node * * Create a new pi node, optionally setting * the node's content. * */ static VALUE rxml_node_new_pi(int argc, VALUE *argv, VALUE klass) { VALUE name = Qnil; VALUE content = Qnil; xmlNodePtr xnode; rb_scan_args(argc, argv, "11", &name, &content); if (NIL_P(name)) { rb_raise(rb_eRuntimeError, "You must provide me with a name for a PI."); } name = rb_obj_as_string(name); if (NIL_P(content)) { xnode = xmlNewPI((xmlChar*) StringValuePtr(name), NULL); } else { content = rb_obj_as_string(content); xnode = xmlNewPI((xmlChar*) StringValuePtr(name), (xmlChar*) StringValueCStr(content)); } if (xnode == NULL) rxml_raise(&xmlLastError); return rxml_node_wrap(xnode); }
/* * call-seq: * XML::Node.initialize(name, content = nil, namespace = nil) -> XML::Node * * Creates a new element with the specified name, content and * namespace. The content and namespace may be nil. */ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self) { VALUE name; VALUE content; VALUE ns; xmlNodePtr xnode = NULL; xmlNsPtr xns = NULL; rb_scan_args(argc, argv, "12", &name, &content, &ns); name = rb_obj_as_string(name); if (!NIL_P(ns)) Data_Get_Struct(ns, xmlNs, xns); xnode = xmlNewNode(xns, (xmlChar*) StringValuePtr(name)); if (xnode == NULL) rxml_raise(&xmlLastError); /* Link the Ruby object to the libxml object and vice-versa. */ xnode->_private = (void*) self; DATA_PTR(self) = xnode; if (!NIL_P(content)) rxml_node_content_set(self, content); return self; }
/* * call-seq: * document.validate_schema(schema) -> (true|false) * * Validate this document against the specified XML::Schema. * * If a block is provided it is used as an error handler for validaten errors. * The block is called with two argument, the message and a flag indication * if the message is an error (true) or a warning (false). */ static VALUE rxml_document_validate_schema(VALUE self, VALUE schema) { xmlSchemaValidCtxtPtr vptr; xmlDocPtr xdoc; xmlSchemaPtr xschema; int is_invalid; Data_Get_Struct(self, xmlDoc, xdoc); Data_Get_Struct(schema, xmlSchema, xschema); vptr = xmlSchemaNewValidCtxt(xschema); xmlSchemaSetValidErrors(vptr, (xmlSchemaValidityErrorFunc) LibXML_validity_error, (xmlSchemaValidityWarningFunc) LibXML_validity_warning, NULL); is_invalid = xmlSchemaValidateDoc(vptr, xdoc); xmlSchemaFreeValidCtxt(vptr); if (is_invalid) { rxml_raise(&xmlLastError); return Qfalse; } else { return Qtrue; } }
/* call-seq: * XML::Reader.file(path) -> XML::Reader * XML::Reader.file(path, :encoding => XML::Encoding::UTF_8, * :options => XML::Parser::Options::NOENT) -> XML::Parser * * Creates a new reader by parsing the specified file or uri. * * You may provide an optional hash table to control how the * parsing is performed. Valid options are: * * encoding - The document encoding, defaults to nil. Valid values * are the encoding constants defined on XML::Encoding. * options - Controls the execution of the parser, defaults to 0. * Valid values are the constants defined on * XML::Parser::Options. Mutliple options can be combined * by using Bitwise OR (|). */ static VALUE rxml_reader_file(int argc, VALUE *argv, VALUE klass) { xmlTextReaderPtr xreader; VALUE path; VALUE options; const char *xencoding = NULL; int xoptions = 0; rb_scan_args(argc, argv, "11", &path, &options); Check_Type(path, T_STRING); if (!NIL_P(options)) { VALUE encoding = Qnil; VALUE parserOptions = Qnil; Check_Type(options, T_HASH); encoding = rb_hash_aref(options, base_uri_SYMBOL); xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding)); parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL); xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions); } xreader = xmlReaderForFile(StringValueCStr(path), xencoding, xoptions); if (xreader == NULL) rxml_raise(&xmlLastError); return rxml_reader_wrap(xreader); }
static VALUE rxml_node_modify_dom(VALUE self, VALUE target, xmlNodePtr (*xmlFunc)(xmlNodePtr, xmlNodePtr)) { xmlNodePtr xnode, xtarget, xresult; if (rb_obj_is_kind_of(target, cXMLNode) == Qfalse) rb_raise(rb_eTypeError, "Must pass an XML::Node object"); xnode = rxml_get_xnode(self); xtarget = rxml_get_xnode(target); if (xtarget->doc != NULL && xtarget->doc != xnode->doc) rb_raise(eXMLError, "Nodes belong to different documents. You must first import the node by calling XML::Document.import"); xmlUnlinkNode(xtarget); /* This target node could be freed here. */ xresult = xmlFunc(xnode, xtarget); if (!xresult) rxml_raise(&xmlLastError); /* Was the target freed? If yes, then wrap the new node */ if (xresult != xtarget) { RDATA(target)->data = xresult; xresult->_private = (void*) target; } return target; }
/* * call-seq: * document.validate_schema(relaxng) -> (true|false) * * Validate this document against the specified XML::RelaxNG. * * If a block is provided it is used as an error handler for validaten errors. * The block is called with two argument, the message and a flag indication * if the message is an error (true) or a warning (false). */ static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng) { xmlRelaxNGValidCtxtPtr vptr; xmlDocPtr xdoc; xmlRelaxNGPtr xrelaxng; int is_invalid; Data_Get_Struct(self, xmlDoc, xdoc); Data_Get_Struct(relaxng, xmlRelaxNG, xrelaxng); vptr = xmlRelaxNGNewValidCtxt(xrelaxng); xmlRelaxNGSetValidErrors(vptr, (xmlRelaxNGValidityErrorFunc) LibXML_validity_error, (xmlRelaxNGValidityWarningFunc) LibXML_validity_warning, NULL); is_invalid = xmlRelaxNGValidateDoc(vptr, xdoc); xmlRelaxNGFreeValidCtxt(vptr); if (is_invalid) { rxml_raise(&xmlLastError); return Qfalse; } else { return Qtrue; } }
/* * call-seq: * context.find("xpath") -> true|false|number|string|XML::XPath::Object * * Executes the provided xpath function. The result depends on the execution * of the xpath statement. It may be true, false, a number, a string or * a node set. */ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr) { xmlXPathContextPtr xctxt; xmlXPathObjectPtr xobject; xmlXPathCompExprPtr xcompexpr; VALUE result; Data_Get_Struct(self, xmlXPathContext, xctxt); if (TYPE(xpath_expr) == T_STRING) { VALUE expression = rb_check_string_type(xpath_expr); xobject = xmlXPathEval((xmlChar*) StringValueCStr(expression), xctxt); } else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression)) { Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr); xobject = xmlXPathCompiledEval(xcompexpr, xctxt); } else { rb_raise(rb_eTypeError, "Argument should be an intance of a String or XPath::Expression"); } 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 (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 = rb_str_new2((const char*)xobject->stringval); xmlXPathFreeObject(xobject); break; default: result = Qnil; xmlXPathFreeObject(xobject); } return result; }
/* * call-seq: * context.disable_cache * * Disables an XPath::Context's built-in cache. */ static VALUE rxml_xpath_context_disable_cache(VALUE self) { xmlXPathContextPtr xctxt; Data_Get_Struct(self, xmlXPathContext, xctxt); if (xmlXPathContextSetCache(xctxt, 0, 0, 0) == -1) rxml_raise(&xmlLastError); return self; }
/* * call-seq: * XML::Node.new_text(content) -> XML::Node * * Create a new text node. * */ static VALUE rxml_node_new_text(VALUE klass, VALUE content) { xmlNodePtr xnode; Check_Type(content, T_STRING); content = rb_obj_as_string(content); xnode = xmlNewText((xmlChar*) StringValueCStr(content)); if (xnode == NULL) rxml_raise(&xmlLastError); return rxml_node_wrap(xnode); }
/* call-seq: * XPath::Expression.new(expression) -> XPath::Expression * * Compiles an XPatch expression. This improves performance * when an XPath expression is called multiple times. * * doc = XML::Document.string('<header><first>hi</first></header>') * expr = XPath::Expression.new('//first') * nodes = doc.find(expr) */ static VALUE rxml_xpath_expression_initialize(VALUE self, VALUE expression) { xmlXPathCompExprPtr compexpr = xmlXPathCompile((const xmlChar*)StringValueCStr(expression)); if (compexpr == NULL) { xmlErrorPtr xerror = xmlGetLastError(); rxml_raise(xerror); } DATA_PTR( self) = compexpr; return self; }
/* * call-seq: * XML::Reader.document(doc) -> XML::Reader * * Create an new reader for the specified document. */ VALUE rxml_reader_document(VALUE klass, VALUE doc) { xmlDocPtr xdoc; xmlTextReaderPtr xreader; Data_Get_Struct(doc, xmlDoc, xdoc); xreader = xmlReaderWalker(xdoc); if (xreader == NULL) rxml_raise(&xmlLastError); return rxml_reader_wrap(xreader); }
/* * call-seq: * document.import(node) -> XML::Node * * Creates a copy of the node that can be inserted into the * current document. */ static VALUE rxml_document_import(VALUE self, VALUE node) { xmlDocPtr xdoc; xmlNodePtr xnode, xresult; Data_Get_Struct(self, xmlDoc, xdoc); Data_Get_Struct(node, xmlNode, xnode); xresult = xmlDocCopyNode(xnode, xdoc, 1); if (xresult == NULL) rxml_raise(&xmlLastError); return rxml_node_wrap(xresult); }
/* * call-seq: * node.next = node * * Insert the specified node as this node's next sibling. */ static VALUE rxml_node_next_set(VALUE self, VALUE rnode) { xmlNodePtr cnode, pnode, ret; if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse) rb_raise(rb_eTypeError, "Must pass an XML::Node object"); Data_Get_Struct(self, xmlNode, pnode); Data_Get_Struct(rnode, xmlNode, cnode); ret = xmlAddNextSibling(pnode, cnode); if (ret == NULL) rxml_raise(&xmlLastError); return (rxml_node_wrap(cXMLNode, ret)); }
/* call-seq: * XML::Parser::Context.string(string) -> XML::Parser::Context * * Creates a new parser context based on the specified string. * * Parameters: * * string - A string that contains the data to parse. */ static VALUE rxml_parser_context_string(VALUE klass, VALUE string) { xmlParserCtxtPtr ctxt; Check_Type(string, T_STRING); if (RSTRING_LEN(string) == 0) rb_raise(rb_eArgError, "Must specify a string with one or more characters"); ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(string), RSTRING_LEN(string)); if (!ctxt) rxml_raise(&xmlLastError); return rxml_parser_context_wrap(ctxt); }
/* * call-seq: * parser.parse -> XML::Document * * Parse the input XML and create an XML::Document with * it's content. If an error occurs, XML::Parser::ParseError * is thrown. */ static VALUE rxml_html_parser_parse(VALUE self) { xmlParserCtxtPtr ctxt; VALUE context = rb_ivar_get(self, CONTEXT_ATTR); Data_Get_Struct(context, xmlParserCtxt, ctxt); if (htmlParseDocument(ctxt) == -1 && ! ctxt->recovery) { if (ctxt->myDoc) xmlFreeDoc(ctxt->myDoc); rxml_raise(&ctxt->lastError); } return rxml_document_wrap(ctxt->myDoc); }
/* * call-seq: * reader.read -> code * * Causes the reader to move to the next node in the stream, exposing its properties. * * Returns true if a node was successfully read or false if there are no more * nodes to read. On errors, an exception is raised.*/ static VALUE rxml_reader_read(VALUE self) { int result = xmlTextReaderRead(rxml_text_reader_get(self)); switch(result) { case -1: rxml_raise(&xmlLastError); return Qnil; break; case 0: return Qfalse; case 1: return Qtrue; default: rb_raise(rb_eRuntimeError, "xmlTextReaderRead did not return -1, 0 or 1. Return value was: %d", result); } }
/* call-seq: * XML::Reader.io(io) -> XML::Reader * XML::Reader.io(io, :encoding => XML::Encoding::UTF_8, * :options => XML::Parser::Options::NOENT) -> XML::Parser * * Creates a new reader by parsing the specified io object. * * You may provide an optional hash table to control how the * parsing is performed. Valid options are: * * base_uri - The base url for the parsed document. * encoding - The document encoding, defaults to nil. Valid values * are the encoding constants defined on XML::Encoding. * options - Controls the execution of the parser, defaults to 0. * Valid values are the constants defined on * XML::Parser::Options. Mutliple options can be combined * by using Bitwise OR (|). */ static VALUE rxml_reader_io(int argc, VALUE *argv, VALUE klass) { xmlTextReaderPtr xreader; VALUE result; VALUE io; VALUE options; char *xbaseurl = NULL; const char *xencoding = NULL; int xoptions = 0; rb_scan_args(argc, argv, "11", &io, &options); if (!NIL_P(options)) { VALUE baseurl = Qnil; VALUE encoding = Qnil; VALUE parserOptions = Qnil; Check_Type(options, T_HASH); baseurl = rb_hash_aref(options, BASE_URI_SYMBOL); xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl); encoding = rb_hash_aref(options, ENCODING_SYMBOL); xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding)); parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL); xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions); } xreader = xmlReaderForIO((xmlInputReadCallback) rxml_read_callback, NULL, (void *) io, xbaseurl, xencoding, xoptions); if (xreader == NULL) rxml_raise(&xmlLastError); result = rxml_reader_wrap(xreader); /* Attach io object to parser so it won't get freed.*/ rb_ivar_set(result, IO_ATTR, io); return result; }
/* * call-seq: * document.save(filename) -> int * document.save(filename, :indent => true, :encoding => 'UTF-8') -> int * * Saves a document to a file. 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 the original encoding of the document (see * #encoding. To override the orginal encoding, use one of the * XML::Encoding encoding constants. */ static VALUE rxml_document_save(int argc, VALUE *argv, VALUE self) { VALUE options = Qnil; VALUE filename = Qnil; xmlDocPtr xdoc; int indent = 1; const char *xfilename; const char *xencoding; int length; rb_scan_args(argc, argv, "11", &filename, &options); Check_Type(filename, T_STRING); xfilename = StringValuePtr(filename); Data_Get_Struct(self, xmlDoc, xdoc); xencoding = xdoc->encoding; 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)); } } length = xmlSaveFormatFileEnc(xfilename, xdoc, xencoding, indent); if (length == -1) rxml_raise(&xmlLastError); return (INT2NUM(length)); }
/* * call-seq: * context.enable_cache(size = nil) * * Enables an XPath::Context's built-in cache. If the cache is * enabled then XPath objects will be cached internally for reuse. * The size parameter controls sets the maximum number of XPath objects * that will be cached per XPath object type (node-set, string, number, * boolean, and misc objects). Set size to nil to use the default * cache size of 100. */ static VALUE rxml_xpath_context_enable_cache(int argc, VALUE *argv, VALUE self) { xmlXPathContextPtr xctxt; VALUE size; int value = -1; Data_Get_Struct(self, xmlXPathContext, xctxt); if (rb_scan_args(argc, argv, "01", &size) == 1) { value = NUM2INT(size); } if (xmlXPathContextSetCache(xctxt, 1, value, 0) == -1) rxml_raise(&xmlLastError); return self; }
/* * call-seq: * initialize(node, "prefix", "href") -> XML::Namespace * * Create a new namespace and adds it to the specified node. * Note this does *not* assign the node to the namespace. * To do that see the XML::Namespaces#namespace method. */ static VALUE rxml_namespace_initialize(VALUE self, VALUE node, VALUE prefix, VALUE href) { xmlNodePtr xnode; xmlChar *xmlPrefix; xmlNsPtr xns; Check_Type(node, T_DATA); Data_Get_Struct(node, xmlNode, xnode); /* Prefix can be null - that means its the default namespace */ xmlPrefix = NIL_P(prefix) ? NULL : (xmlChar *)StringValuePtr(prefix); xns = xmlNewNs(xnode, (xmlChar*) StringValuePtr(href), xmlPrefix); if (!xns) rxml_raise(&xmlLastError); xns->_private = (void*)self; DATA_PTR(self) = xns; return self; }
/* * call-seq: * context.encoding = XML::Encoding::UTF_8 * * Sets the character encoding for this context. */ static VALUE rxml_parser_context_encoding_set(VALUE self, VALUE encoding) { xmlParserCtxtPtr ctxt; int result; const char* xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(encoding)); xmlCharEncodingHandlerPtr hdlr = xmlFindCharEncodingHandler(xencoding); if (!hdlr) rb_raise(rb_eRuntimeError, "Unknown encoding: %s", encoding); Data_Get_Struct(self, xmlParserCtxt, ctxt); result = xmlSwitchToEncoding(ctxt, hdlr); if (result != 0) rxml_raise(&xmlLastError); if (ctxt->encoding != NULL) xmlFree((xmlChar *) ctxt->encoding); ctxt->encoding = xmlStrdup((const xmlChar *) xencoding); return self; }
/* * call-seq: * document.validate(dtd) -> (true|false) * * Validate this document against the specified XML::DTD. * If the document is valid the method returns true. Otherwise an * exception is raised with validation information. */ static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd) { xmlValidCtxt ctxt; xmlDocPtr xdoc; xmlDtdPtr xdtd; Data_Get_Struct(self, xmlDoc, xdoc); Data_Get_Struct(dtd, xmlDtd, xdtd); /* Setup context */ memset(&ctxt, 0, sizeof(xmlValidCtxt)); if (xmlValidateDtd(&ctxt, xdoc, xdtd)) { return Qtrue; } else { rxml_raise(&xmlLastError); return Qfalse; } }
/* * call-seq: * node.sibling(node) -> XML::Node * * Add the specified node as a sibling of this node. */ static VALUE rxml_node_sibling_set(VALUE self, VALUE rnode) { xmlNodePtr cnode, pnode, ret; VALUE obj; if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse) rb_raise(rb_eTypeError, "Must pass an XML::Node object"); Data_Get_Struct(self, xmlNode, pnode); Data_Get_Struct(rnode, xmlNode, cnode); ret = xmlAddSibling(pnode, cnode); if (ret == NULL) rxml_raise(&xmlLastError); if (ret->_private == NULL) obj = rxml_node_wrap(cXMLNode, ret); else obj = (VALUE) ret->_private; return obj; }
/* * call-seq: * XML::Node.new_comment(content = nil) -> XML::Node * * Create a new comment node, optionally setting * the node's content. * */ static VALUE rxml_node_new_comment(int argc, VALUE *argv, VALUE klass) { VALUE content = Qnil; xmlNodePtr xnode; rb_scan_args(argc, argv, "01", &content); if (NIL_P(content)) { xnode = xmlNewComment(NULL); } else { content = rb_obj_as_string(content); xnode = xmlNewComment((xmlChar*) StringValueCStr(content)); } if (xnode == NULL) rxml_raise(&xmlLastError); return rxml_node_wrap(xnode); }
/* * call-seq: * context.find("xpath") -> XML::XPath::Object * * Find nodes matching the specified XPath expression */ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr) { xmlXPathContextPtr xctxt; xmlXPathObjectPtr xobject; xmlXPathCompExprPtr xcompexpr; VALUE result; Data_Get_Struct(self, xmlXPathContext, xctxt); if (TYPE(xpath_expr) == T_STRING) { VALUE expression = rb_check_string_type(xpath_expr); xobject = xmlXPathEval((xmlChar*) StringValueCStr(expression), xctxt); } else if (rb_obj_is_kind_of(xpath_expr, cXMLXPathExpression)) { Data_Get_Struct(xpath_expr, xmlXPathCompExpr, xcompexpr); xobject = xmlXPathCompiledEval(xcompexpr, xctxt); } else { rb_raise(rb_eTypeError, "Argument should be an intance of a String or XPath::Expression"); } 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); } result = rxml_xpath_object_wrap(xobject); rb_iv_set(result, "@context", self); return result; }
/* call-seq: * XML::Reader.string(io) -> XML::Reader * XML::Reader.string(io, :encoding => XML::Encoding::UTF_8, * :options => XML::Parser::Options::NOENT) -> XML::Parser * * Creates a new reader by parsing the specified string. * * You may provide an optional hash table to control how the * parsing is performed. Valid options are: * * base_uri - The base url for the parsed document. * encoding - The document encoding, defaults to nil. Valid values * are the encoding constants defined on XML::Encoding. * options - Controls the execution of the parser, defaults to 0. * Valid values are the constants defined on * XML::Parser::Options. Mutliple options can be combined * by using Bitwise OR (|). */ static VALUE rxml_reader_string(int argc, VALUE *argv, VALUE klass) { xmlTextReaderPtr xreader; VALUE string; VALUE options; char *xbaseurl = NULL; const char *xencoding = NULL; int xoptions = 0; rb_scan_args(argc, argv, "11", &string, &options); Check_Type(string, T_STRING); if (!NIL_P(options)) { VALUE baseurl = Qnil; VALUE encoding = Qnil; VALUE parserOptions = Qnil; Check_Type(options, T_HASH); baseurl = rb_hash_aref(options, base_uri_SYMBOL); xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl); encoding = rb_hash_aref(options, ENCODING_SYMBOL); xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding)); parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL); xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions); } xreader = xmlReaderForMemory(StringValueCStr(string), RSTRING_LEN(string), xbaseurl, xencoding, xoptions); if (xreader == NULL) rxml_raise(&xmlLastError); return rxml_reader_wrap(xreader); }