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::XPathcontext for the specified document.
Instance Attribute Summary
-
#node=(node)
writeonly
Set the current node used by the
::LibXML::XML::XPathengine.
Instance Method Summary
-
#disable_cache
Disables an XPath::Context’s built-in cache.
-
#doc ⇒ document
Obtain the
::LibXML::XML::Documentthis 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;
}