class Nokogiri::XML::XPathContext - nokogiri-1.18.10 Documentation

# class Nokogiri::XML::XPathContext

`XPathContext` is the entry point for searching a `Document` by using `XPath`.

### Public Class Methods

new(node) click to toggle source

Create a new `XPathContext` with `node` as the context node.

    static VALUE
    noko_xml_xpath_context_new(VALUE klass, VALUE rb_node)
    {
      xmlNodePtr c_node;
      xmlXPathContextPtr c_context;
      VALUE rb_context;

      Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

    #if LIBXML_VERSION < 21000
      xmlXPathInit(); /* deprecated in 40483d0 */
    #endif

      c_context = xmlXPathNewContext(c_node->doc);
      c_context->node = c_node;

      xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
      xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);

      xmlXPathRegisterFuncNS(c_context,
                             (const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
                             noko_xml_xpath_context_xpath_func_css_class);
      xmlXPathRegisterFuncNS(c_context,
                             (const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
                             noko_xml_xpath_context_xpath_func_local_name_is);

      rb_context = TypedData_Wrap_Struct(klass, &_noko_xml_xpath_context_type, c_context);

      return rb_context;
    }

### Public Instance Methods

evaluate(search_path, handler = nil) → Object click to toggle source

Evaluate the `search_path` query.

Returns

  an object of the appropriate type for the query, which could be `NodeSet`, a `String`,

a `Float`, or a boolean.

    static VALUE
    noko_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
    {
      xmlXPathContextPtr c_context;
      VALUE rb_expression = Qnil;
      VALUE rb_function_lookup_handler = Qnil;
      xmlChar *c_expression_str = NULL;
      VALUE rb_errors = rb_ary_new();
      xmlXPathObjectPtr c_xpath_object;
      VALUE rb_xpath_object = Qnil;

      TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);

      rb_scan_args(argc, argv, "11", &rb_expression, &rb_function_lookup_handler);

      c_expression_str = (xmlChar *)StringValueCStr(rb_expression);

      if (Qnil != rb_function_lookup_handler) {
        /* FIXME: not sure if this is the correct place to shove private data. */
        c_context->userData = (void *)rb_function_lookup_handler;
        xmlXPathRegisterFuncLookup(
          c_context,
          _noko_xml_xpath_context_handler_lookup,
          (void *)rb_function_lookup_handler
        );
      }

      /* TODO: use xmlXPathSetErrorHandler (as of 2.13.0) */
      xmlSetStructuredErrorFunc((void *)rb_errors, noko__error_array_pusher);
      xmlSetGenericErrorFunc((void *)rb_errors, _noko_xml_xpath_context__generic_exception_pusher);

      c_xpath_object = xmlXPathEvalExpression(c_expression_str, c_context);

      xmlSetStructuredErrorFunc(NULL, NULL);
      xmlSetGenericErrorFunc(NULL, NULL);

      xmlXPathRegisterFuncLookup(c_context, NULL, NULL);

      if (c_xpath_object == NULL) {
        rb_exc_raise(rb_ary_entry(rb_errors, 0));
      }

      rb_xpath_object = _noko_xml_xpath_context__xpath2ruby(c_xpath_object, c_context);
      if (rb_xpath_object == Qundef) {
        rb_xpath_object = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
      }

      xmlXPathFreeNodeSetList(c_xpath_object);

      return rb_xpath_object;
    }

register_namespaces(namespaces) click to toggle source

Register namespaces in `namespaces`

    # File lib/nokogiri/xml/xpath_context.rb, line 8
    def register_namespaces(namespaces)
      namespaces.each do |key, value|
        key = key.to_s.gsub(/.*:/, "") # strip off 'xmlns:' or 'xml:'

        register_ns(key, value)
      end
    end

register_ns(prefix, uri) → Nokogiri::XML::XPathContext click to toggle source

Register the namespace with `prefix` and `uri` for use in future queries. Passing a uri of `nil` will unregister the namespace.

Returns

  `self`

    static VALUE
    noko_xml_xpath_context_register_ns(VALUE rb_context, VALUE prefix, VALUE uri)
    {
      xmlXPathContextPtr c_context;
      const xmlChar *ns_uri;

      TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);

      if (NIL_P(uri)) {
        ns_uri = NULL;
      } else {
        ns_uri = (const xmlChar *)StringValueCStr(uri);
      }

      xmlXPathRegisterNs(c_context, (const xmlChar *)StringValueCStr(prefix), ns_uri);

      return rb_context;
    }

register_variable(name, value) → Nokogiri::XML::XPathContext click to toggle source

Register the variable `name` with `value` for use in future queries. Passing a value of `nil` will unregister the variable.

Returns

  `self`

    static VALUE
    noko_xml_xpath_context_register_variable(VALUE rb_context, VALUE name, VALUE value)
    {
      xmlXPathContextPtr c_context;
      xmlXPathObjectPtr xmlValue;

      TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);

      if (NIL_P(value)) {
        xmlValue = NULL;
      } else {
        xmlValue = xmlXPathNewCString(StringValueCStr(value));
      }

      xmlXPathRegisterVariable(c_context, (const xmlChar *)StringValueCStr(name), xmlValue);

      return rb_context;
    }

register_variables(binds) click to toggle source

    # File lib/nokogiri/xml/xpath_context.rb, line 16
    def register_variables(binds)
      return if binds.nil?

      binds.each do |key, value|
        key = key.to_s

        register_variable(key, value)
      end
    end