Class: Nokogiri::XML::XPathContext

Inherits:
Object
  • Object
show all
Defined in:
lib/nokogiri/xml/xpath_context.rb,
ext/nokogiri/xml_xpath_context.c

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(node) ⇒ Object

Create a new XPathContext with node as the context node.



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'ext/nokogiri/xml_xpath_context.c', line 432

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;
}

Instance Method Details

#evaluate(search_path, handler = nil) ⇒ Object

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.



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'ext/nokogiri/xml_xpath_context.c', line 374

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;
}

#node=(rb_node) ⇒ Object

:nodoc:



465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'ext/nokogiri/xml_xpath_context.c', line 465

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

  TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
  Noko_Node_Get_Struct(rb_node, xmlNode, c_node);

  c_context->doc = c_node->doc;
  c_context->node = c_node;

  return rb_node;
}

#register_namespaces(namespaces) ⇒ Object

Register namespaces in namespaces



8
9
10
11
12
13
14
# 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) ⇒ Object

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

[Returns] self



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'ext/nokogiri/xml_xpath_context.c', line 141

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) ⇒ Object

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

[Returns] self



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'ext/nokogiri/xml_xpath_context.c', line 169

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) ⇒ Object



16
17
18
19
20
21
22
23
24
# 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