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.



422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'ext/nokogiri/xml_xpath_context.c', line 422

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.



364
365
366
367
368
369
370
371
372
373
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
# File 'ext/nokogiri/xml_xpath_context.c', line 364

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:



455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'ext/nokogiri/xml_xpath_context.c', line 455

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



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'ext/nokogiri/xml_xpath_context.c', line 131

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



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'ext/nokogiri/xml_xpath_context.c', line 159

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