Class: LibXML::XML::XPath::Context
Relationships & Source Files | |
Inherits: | Object |
Defined in: | ext/libxml/ruby_xml_xpath_context.c, ext/libxml/ruby_xml_xpath_context.c |
Overview
The Context
class is used to evaluate ::LibXML::XML::XPath
expressions. Generally, you should not directly use this class, but instead use the Document#find and Node#find methods.
doc = XML::Document.string('<header>content</header>')
context = XPath::Context.new(doc)
context.node = doc.root
context.register_namespaces_from_node(doc.root)
nodes = context.find('/header')
Class Method Summary
-
XPath::Context.new(doc) ⇒ Context
constructor
Creates a new
::LibXML::XML::XPath
context for the specified document.
Instance Attribute Summary
-
#node=(node)
writeonly
Set the current node used by the
::LibXML::XML::XPath
engine.
Instance Method Summary
-
#disable_cache
Disables an XPath::Context’s built-in cache.
-
#doc ⇒ document
Obtain the
::LibXML::XML::Document
this node belongs to. -
#enable_cache(size = nil)
Enables an XPath::Context’s built-in cache.
-
#find("xpath") ⇒ Boolean
Executes the provided xpath function.
-
#register_namespace(prefix, uri) ⇒ Boolean
Register the specified namespace URI with the specified prefix in this context.
-
#register_namespaces(["prefix:uri"]) ⇒ self
Register the specified namespaces in this context.
-
#register_namespaces_from_node(node) ⇒ self
Helper method to read in namespaces defined on a node.
Constructor Details
XPath::Context.new(doc) ⇒ Context
Creates a new ::LibXML::XML::XPath
context for the specified document. The context can then be used to evaluate an ::LibXML::XML::XPath
expression.
doc = XML::Document.string('<header><first>hi</first></header>')
context = XPath::Context.new(doc)
nodes = XPath::Object.new('//first', context)
nodes.length == 1
# File 'ext/libxml/ruby_xml_xpath_context.c', line 58
static VALUE rxml_xpath_context_initialize(VALUE self, VALUE document) { xmlDocPtr xdoc; if (rb_obj_is_kind_of(document, cXMLDocument) != Qtrue) { rb_raise(rb_eTypeError, "Supplied argument must be a document or node."); } Data_Get_Struct(document, xmlDoc, xdoc); DATA_PTR(self) = xmlXPathNewContext(xdoc); return self; }
Instance Attribute Details
#node=(node) (writeonly)
# File 'ext/libxml/ruby_xml_xpath_context.c', line 250
static VALUE rxml_xpath_context_node_set(VALUE self, VALUE node) { xmlXPathContextPtr xctxt; xmlNodePtr xnode; Data_Get_Struct(self, xmlXPathContext, xctxt); Data_Get_Struct(node, xmlNode, xnode); xctxt->node = xnode; return node; }
Instance Method Details
#disable_cache
Disables an XPath::Context’s built-in cache.
# File 'ext/libxml/ruby_xml_xpath_context.c', line 334
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(xmlGetLastError()); return self; }
#doc ⇒ document
Obtain the ::LibXML::XML::Document
this node belongs to.
# File 'ext/libxml/ruby_xml_xpath_context.c', line 79
static VALUE rxml_xpath_context_doc(VALUE self) { xmlDocPtr xdoc = NULL; xmlXPathContextPtr ctxt; Data_Get_Struct(self, xmlXPathContext, ctxt); xdoc = ctxt->doc; return rxml_document_wrap(xdoc); }
#enable_cache(size = nil)
Enables an XPath::Context’s built-in cache. If the cache is enabled then ::LibXML::XML::XPath
objects will be cached internally for reuse. The size parameter controls sets the maximum number of ::LibXML::XML::XPath
objects that will be cached per ::LibXML::XML::XPath
object type (node-set, string, number, boolean, and misc objects). Set size to nil to use the default cache size of 100.
# File 'ext/libxml/ruby_xml_xpath_context.c', line 308
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(xmlGetLastError()); return self; }
#find("xpath") ⇒ Boolean
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.
# File 'ext/libxml/ruby_xml_xpath_context.c', line 269
static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr) { xmlXPathContextPtr xctxt; xmlXPathObjectPtr xobject; xmlXPathCompExprPtr xcompexpr; 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 instance of a String or XPath::Expression"); } return rxml_xpath_to_value(xctxt, xobject); }
#register_namespace(prefix, uri) ⇒ Boolean
Register the specified namespace URI with the specified prefix in this context.
context.register_namespace('xi', 'http://www.w3.org/2001/XInclude')
# File 'ext/libxml/ruby_xml_xpath_context.c', line 98
static VALUE rxml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri) { xmlXPathContextPtr ctxt; Data_Get_Struct(self, xmlXPathContext, ctxt); /* Prefix could be a symbol. */ prefix = rb_obj_as_string(prefix); if (xmlXPathRegisterNs(ctxt, (xmlChar*) StringValuePtr(prefix), (xmlChar*) StringValuePtr(uri)) == 0) { return (Qtrue); } else { /* Should raise an exception, IMHO (whose?, why shouldnt it? -danj)*/ rb_warning("register namespace failed"); return (Qfalse); } }
#register_namespaces(["prefix:uri"]) ⇒ self
Register the specified namespaces in this context. There are three different forms that libxml accepts. These include a string, an array of strings, or a hash table:
context.register_namespaces('xi:http://www.w3.org/2001/XInclude')
context.register_namespaces(['xlink:http://www.w3.org/1999/xlink',
'xi:http://www.w3.org/2001/XInclude')
context.register_namespaces('xlink' => 'http://www.w3.org/1999/xlink',
'xi' => 'http://www.w3.org/2001/XInclude')
# File 'ext/libxml/ruby_xml_xpath_context.c', line 196
static VALUE rxml_xpath_context_register_namespaces(VALUE self, VALUE nslist) { char *cp; long i; VALUE rprefix, ruri; xmlXPathContextPtr xctxt; Data_Get_Struct(self, xmlXPathContext, xctxt); /* Need to loop through the 2nd argument and iterate through the * list of namespaces that we want to allow */ switch (TYPE(nslist)) { case T_STRING: cp = strchr(StringValuePtr(nslist), (int) ':'); if (cp == NULL) { rprefix = nslist; ruri = Qnil; } else { rprefix = rb_str_new(StringValuePtr(nslist), (long) ((intptr_t) cp - (intptr_t)StringValuePtr(nslist))); ruri = rxml_new_cstr((const xmlChar*)&cp[1], xctxt->doc->encoding); } /* Should test the results of this */ rxml_xpath_context_register_namespace(self, rprefix, ruri); break; case T_ARRAY: for (i = 0; i < RARRAY_LEN(nslist); i++) { rxml_xpath_context_register_namespaces(self, RARRAY_PTR(nslist)[i]); } break; case T_HASH: rb_hash_foreach(nslist, iterate_ns_hash, self); break; default: rb_raise( rb_eArgError, "Invalid argument type, only accept string, array of strings, or an array of arrays"); } return self; }
#register_namespaces_from_node(node) ⇒ self
# File 'ext/libxml/ruby_xml_xpath_context.c', line 128
static VALUE rxml_xpath_context_register_namespaces_from_node(VALUE self, VALUE node) { xmlXPathContextPtr xctxt; xmlNodePtr xnode; xmlNsPtr *xnsArr; Data_Get_Struct(self, xmlXPathContext, xctxt); if (rb_obj_is_kind_of(node, cXMLDocument) == Qtrue) { xmlDocPtr xdoc; Data_Get_Struct(node, xmlDoc, xdoc); xnode = xmlDocGetRootElement(xdoc); } else if (rb_obj_is_kind_of(node, cXMLNode) == Qtrue) { Data_Get_Struct(node, xmlNode, xnode); } else { rb_raise(rb_eTypeError, "The first argument must be a document or node."); } xnsArr = xmlGetNsList(xnode->doc, xnode); if (xnsArr) { xmlNsPtr xns = *xnsArr; while (xns) { /* If there is no prefix, then this is the default namespace. Skip it for now. */ if (xns->prefix) { VALUE prefix = rxml_new_cstr(xns->prefix, xctxt->doc->encoding); VALUE uri = rxml_new_cstr(xns->href, xctxt->doc->encoding); rxml_xpath_context_register_namespace(self, prefix, uri); } xns = xns->next; } xmlFree(xnsArr); } return self; }