/* 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);
}
Esempio n. 2
0
/*
 * 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);
}
Esempio n. 3
0
/*
 * 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;
}
Esempio n. 5
0
/*
 * 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);
}
Esempio n. 6
0
/*
 * 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;
}
Esempio n. 7
0
/*
 * 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;
  }
}
Esempio n. 8
0
/* 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);
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
/*
 * 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;
  }
}
Esempio n. 11
0
/*
 * 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;
}
Esempio n. 12
0
/*
 * 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;
}
Esempio n. 13
0
/*
 * 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;
}
Esempio n. 15
0
/*
 * 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);
}
Esempio n. 16
0
/*
 * 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);
}
Esempio n. 17
0
/*
 * 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);
}
Esempio n. 19
0
/*
 * 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);
}
Esempio n. 20
0
/*
 * 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);
  }
}
Esempio n. 21
0
/* 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;
}
Esempio n. 22
0
/*
 * 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));
}
Esempio n. 23
0
/*
 * 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;
}
Esempio n. 24
0
/*
 * 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;
}
Esempio n. 26
0
/*
 * 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;
  }
}
Esempio n. 27
0
/*
 * 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;
}
Esempio n. 28
0
/*
 * 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);
}
Esempio n. 29
0
/*
 * 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;
}
Esempio n. 30
0
/* 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);
}