/*
 * 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.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;
}
Example #3
0
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;
}