Skip to content

Commit

Permalink
adding xml xpath context as an actual object
Browse files Browse the repository at this point in the history
  • Loading branch information
tenderlove committed Sep 30, 2008
1 parent 482655d commit 8c87f06
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 30 deletions.
1 change: 1 addition & 0 deletions ext/nokogiri/native.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ void Init_native()
init_xml_node();
init_xml_text();
init_xml_node_set();
init_xml_xpath_context();
init_xml_xpath();
init_xml_sax_parser();
init_xml_reader();
Expand Down
1 change: 1 addition & 0 deletions ext/nokogiri/native.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <xml_text.h>
#include <xml_node_set.h>
#include <xml_xpath.h>
#include <xml_xpath_context.h>
#include <xml_sax_parser.h>
#include <xml_reader.h>
#include <html_sax_parser.h>
Expand Down
43 changes: 15 additions & 28 deletions ext/nokogiri/xml_xpath.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#include <xml_xpath.h>

static void free_xpath_object(xmlXPathObjectPtr xpath)
static void deallocate(xmlXPathObjectPtr xpath)
{
xmlXPathFreeNodeSetList(xpath); // despite the name, this frees the xpath but not the contained node set
xmlXPathFreeNodeSetList(xpath); // despite the name, this frees the xpath but not the contained node set
}

VALUE Nokogiri_wrap_xml_xpath(xmlXPathObjectPtr xpath)
{
return Data_Wrap_Struct(cNokogiriXmlXpath, 0, deallocate, xpath);
}

/*
Expand All @@ -17,36 +22,18 @@ static VALUE node_set(VALUE self)
Data_Get_Struct(self, xmlXPathObject, xpath);

if (xpath->nodesetval)
return Nokogiri_wrap_xml_node_set(xpath->nodesetval);
else
return Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL));
}
return Nokogiri_wrap_xml_node_set(xpath->nodesetval);

static VALUE new(VALUE klass, VALUE nodeobj, VALUE search_path)
{
xmlXPathInit();

xmlNodePtr node ;
Data_Get_Struct(nodeobj, xmlNode, node);

xmlXPathContextPtr ctx = xmlXPathNewContext(node->doc);
ctx->node = node ;
xmlChar* query = (xmlChar *)StringValuePtr(search_path) ;
xmlXPathObjectPtr xpath = xmlXPathEvalExpression(query, ctx );
if(xpath == NULL) {
xmlXPathFreeContext(ctx);
rb_raise(rb_eRuntimeError, "Couldn't evaluate expression '%s'", query);
}
VALUE self = Data_Wrap_Struct(klass, NULL, free_xpath_object, xpath);
xmlXPathFreeContext(ctx);

return self;
return Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL));
}

VALUE cNokogiriXmlXpath ;
VALUE cNokogiriXmlXpath;
void init_xml_xpath(void)
{
VALUE klass = cNokogiriXmlXpath = rb_eval_string("Nokogiri::XML::XPath");
rb_define_singleton_method(klass, "new", new, 2);
VALUE module = rb_define_module("Nokogiri");
VALUE xml = rb_define_module_under(module, "XML");
VALUE klass = rb_define_class_under(xml, "XPath", rb_cObject);

cNokogiriXmlXpath = klass;
rb_define_method(klass, "node_set", node_set, 0);
}
4 changes: 3 additions & 1 deletion ext/nokogiri/xml_xpath.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <native.h>

void init_xml_xpath();
VALUE Nokogiri_wrap_xml_xpath(xmlXPathObjectPtr xpath);

extern VALUE cNokogiriXmlXpath ;
extern VALUE cNokogiriXmlXpath;
#endif

51 changes: 51 additions & 0 deletions ext/nokogiri/xml_xpath_context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <xml_xpath_context.h>

static void deallocate(xmlXPathContextPtr ctx)
{
xmlXPathFreeContext(ctx);
}

/*
* call-seq:
* evaluate(search_path)
*
* Evaluate the +search_path+ returning an XML::XPath object.
*/
static VALUE evaluate(VALUE self, VALUE search_path)
{
xmlXPathContextPtr ctx;
Data_Get_Struct(self, xmlXPathContext, ctx);

xmlChar* query = (xmlChar *)StringValuePtr(search_path);
xmlXPathObjectPtr xpath = xmlXPathEvalExpression(query, ctx);
if(xpath == NULL) {
xmlXPathFreeContext(ctx);
rb_raise(rb_eRuntimeError, "Couldn't evaluate expression '%s'", query);
}
return Nokogiri_wrap_xml_xpath(xpath);
}

static VALUE new(VALUE klass, VALUE nodeobj)
{
xmlXPathInit();

xmlNodePtr node ;
Data_Get_Struct(nodeobj, xmlNode, node);

xmlXPathContextPtr ctx = xmlXPathNewContext(node->doc);
ctx->node = node ;
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
}

VALUE cNokogiriXmlXpathContext;
void init_xml_xpath_context(void)
{
VALUE module = rb_define_module("Nokogiri");
VALUE xml = rb_define_module_under(module, "XML");
VALUE klass = rb_define_class_under(xml, "XPathContext", rb_cObject);

cNokogiriXmlXpathContext = klass;

rb_define_singleton_method(klass, "new", new, 1);
rb_define_method(klass, "evaluate", evaluate, 1);
}
9 changes: 9 additions & 0 deletions ext/nokogiri/xml_xpath_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef NOKOGIRI_XML_XPATH_CONTEXT
#define NOKOGIRI_XML_XPATH_CONTEXT

#include <native.h>

void init_xml_xpath_context();

extern VALUE cNokogiriXmlXpathContext;
#endif
2 changes: 1 addition & 1 deletion lib/nokogiri/xml/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def find(*paths)

def find_by_xpath *paths
sets = paths.map { |path|
set = XPath.new(self, path).node_set
set = XPathContext.new(self).evaluate(path).node_set
set.document = document
document.decorate(set)
set
Expand Down

0 comments on commit 8c87f06

Please sign in to comment.