nokogiri 1.0.7 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

@@ -1,3 +1,17 @@
1
+ === HEAD
2
+
3
+ * 新しい機能
4
+
5
+ * カスタム XPath 機能はある。( 参照 Nokogiri::XML::Node#xpath )
6
+ * カスタム CSS 擬似クラスと機能はある。( 参照 Nokogiri::XML::Node#css )
7
+ * Nokogiri::XML::Node#<< は参照に子ノードを添える
8
+
9
+ * バグの修正
10
+
11
+ * mutex が CSS のキャッシュのアクセスをロックする
12
+ * GCC 3.3.5 のビルドが修正された
13
+ * XML::Node#to_xml は
14
+
1
15
  === 1.0.7
2
16
 
3
17
  * バグの修正
@@ -1,3 +1,19 @@
1
+ === 1.1.0
2
+
3
+ * New Features
4
+
5
+ * Custom XPath functions are now supported. See Nokogiri::XML::Node#xpath
6
+ * Custom CSS pseudo classes are now supported. See Nokogiri::XML::Node#css
7
+ * Nokogiri::XML::Node#<< will add a child to the current node
8
+
9
+ * Bugfixes
10
+
11
+ * Mutex lock on CSS cache access
12
+ * Fixed build problems with GCC 3.3.5
13
+ * XML::Node#to_xml now takes an indentation argument
14
+ * XML::Node#dup takes an optional depth argument
15
+ * XML::Node#add_previous_sibling returns new sibling node.
16
+
1
17
  === 1.0.7
2
18
 
3
19
  * Bugfixes
@@ -47,6 +47,7 @@ lib/nokogiri/css/generated_tokenizer.rb
47
47
  lib/nokogiri/css/node.rb
48
48
  lib/nokogiri/css/parser.rb
49
49
  lib/nokogiri/css/parser.y
50
+ lib/nokogiri/css/selector_handler.rb
50
51
  lib/nokogiri/css/syntax_error.rb
51
52
  lib/nokogiri/css/tokenizer.rb
52
53
  lib/nokogiri/css/tokenizer.rex
@@ -85,6 +86,7 @@ lib/nokogiri/xml/text.rb
85
86
  lib/nokogiri/xml/xpath.rb
86
87
  lib/nokogiri/xml/xpath/syntax_error.rb
87
88
  lib/nokogiri/xml/xpath_context.rb
89
+ lib/nokogiri/xml/xpath_handler.rb
88
90
  lib/nokogiri/xslt.rb
89
91
  lib/nokogiri/xslt/stylesheet.rb
90
92
  test/css/test_nthiness.rb
@@ -92,6 +94,8 @@ test/css/test_parser.rb
92
94
  test/css/test_tokenizer.rb
93
95
  test/css/test_xpath_visitor.rb
94
96
  test/files/dont_hurt_em_why.xml
97
+ test/files/exslt.xml
98
+ test/files/exslt.xslt
95
99
  test/files/staff.xml
96
100
  test/files/staff.xslt
97
101
  test/files/tlm.html
@@ -132,4 +136,5 @@ test/xml/test_dtd.rb
132
136
  test/xml/test_node.rb
133
137
  test/xml/test_node_set.rb
134
138
  test/xml/test_text.rb
139
+ test/xml/test_xpath.rb
135
140
  vendor/hoe.rb
@@ -20,7 +20,7 @@ Nokogiri はHTMLやXMLやSAXやXSLTやReaderのパーサーです。
20
20
 
21
21
  これはスピードテストです:
22
22
 
23
- * http://gist.github.com/22176
23
+ * http://gist.github.com/24605
24
24
 
25
25
  NokogiriはHpricotの代わりに使用出来る。
26
26
  その互換性は簡単に正しいCSSとXPathを使用する事が出来る。
data/README.txt CHANGED
@@ -22,7 +22,7 @@ correctly implemented CSS3 selector support as well as XPath support.
22
22
 
23
23
  Here is a speed test:
24
24
 
25
- * http://gist.github.com/22176
25
+ * http://gist.github.com/24605
26
26
 
27
27
  Nokogiri also features an Hpricot compatibility layer to help ease the change
28
28
  to using correct CSS and XPath.
data/Rakefile CHANGED
@@ -231,9 +231,13 @@ end
231
231
 
232
232
  def test_suite_cmdline
233
233
  require 'find'
234
+ match = ENV['MATCH'] ? /#{ENV['MATCH']}/ : /./
235
+
234
236
  files = []
235
237
  Find.find("test") do |f|
236
- files << f if File.basename(f) =~ /.*test.*\.rb$/
238
+ basename = File.basename(f)
239
+
240
+ files << f if basename =~ /.*test.*\.rb$/ && basename =~ match
237
241
  end
238
242
  cmdline = "ruby -w -I.:lib:ext:test -rtest/unit -e '%w[#{files.join(' ')}].each {|f| require f}'"
239
243
  end
@@ -328,11 +332,4 @@ unless windows
328
332
  Rake::Task[:check_manifest].prerequisites << GENERATED_TOKENIZER
329
333
  end
330
334
 
331
- # Evil evil hack. Do not run tests when gem installs
332
- if ENV['RUBYARCHDIR']
333
- prereqs = Rake::Task[:default].prerequisites
334
- prereqs.clear
335
- prereqs << :build
336
- end
337
-
338
335
  # vim: syntax=Ruby
@@ -6,6 +6,8 @@ ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
6
6
  LIBDIR = Config::CONFIG['libdir']
7
7
  INCLUDEDIR = Config::CONFIG['includedir']
8
8
 
9
+ use_macports = !(defined?(RUBY_ENGINE) && RUBY_ENGINE != 'ruby')
10
+
9
11
  $CFLAGS << " #{ENV["CFLAGS"]}"
10
12
  if Config::CONFIG['target_os'] == 'mingw32'
11
13
  $CFLAGS << " -DXP_WIN -DXP_WIN32"
@@ -13,16 +15,36 @@ else
13
15
  $CFLAGS << " -g -DXP_UNIX"
14
16
  end
15
17
 
16
- $CFLAGS << " -O3 -Wall -Wextra -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline"
18
+ $LIBPATH << "/opt/local/lib" if use_macports
19
+
20
+ $CFLAGS << " -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline"
17
21
 
18
22
  if Config::CONFIG['target_os'] == 'mingw32'
19
23
  find_library('xml2', 'xmlParseDoc',
20
24
  File.join(ROOT, 'cross', 'libxml2-2.7.2.win32', 'bin'))
21
25
  find_library('xslt', 'xsltParseStylesheetDoc',
22
26
  File.join(ROOT, 'cross', 'libxslt-1.1.24.win32', 'bin'))
27
+ find_library('exslt', 'exsltFuncRegister',
28
+ File.join(ROOT, 'cross', 'libxslt-1.1.24.win32', 'bin'))
23
29
  else
24
- find_library('xml2', 'xmlParseDoc', LIBDIR)
25
- find_library('xslt', 'xsltParseStylesheetDoc', LIBDIR)
30
+ find_library('xml2', 'xmlParseDoc',
31
+ LIBDIR,
32
+ '/opt/local/lib',
33
+ '/usr/local/lib',
34
+ '/usr/lib'
35
+ )
36
+ find_library('xslt', 'xsltParseStylesheetDoc',
37
+ LIBDIR,
38
+ '/opt/local/lib',
39
+ '/usr/local/lib',
40
+ '/usr/lib'
41
+ )
42
+ find_library('exslt', 'exsltFuncRegister',
43
+ LIBDIR,
44
+ '/opt/local/lib',
45
+ '/usr/local/lib',
46
+ '/usr/lib'
47
+ )
26
48
  end
27
49
 
28
50
 
@@ -36,18 +58,35 @@ if Config::CONFIG['target_os'] == 'mingw32'
36
58
  unless find_header('libxslt/libxslt.h', header)
37
59
  abort "need libxslt"
38
60
  end
61
+ unless find_header('libexslt/libexslt.h', header)
62
+ abort "need libexslt"
63
+ end
39
64
 
40
65
  header = File.join(ROOT, 'cross', 'iconv-1.9.2.win32', 'include')
41
66
  unless find_header('iconv.h', header)
42
67
  abort "need iconv"
43
68
  end
44
69
  else
45
- unless find_header('libxml/xmlversion.h',
46
- File.join(INCLUDEDIR, "libxml2"), '/usr/include/libxml2'
47
- )
70
+ HEADER_DIRS = [
71
+ File.join(INCLUDEDIR, "libxml2"),
72
+ INCLUDEDIR,
73
+ '/usr/include/libxml2',
74
+ '/usr/local/include/libxml2'
75
+ ]
76
+
77
+ [
78
+ '/opt/local/include/libxml2',
79
+ '/opt/local/include',
80
+ ].each { |x| HEADER_DIRS.unshift(x) } if use_macports
81
+
82
+ unless find_header('libxml/xmlversion.h', *HEADER_DIRS)
48
83
  abort "need libxml"
49
84
  end
50
- unless find_header('libxslt/xslt.h', INCLUDEDIR, '/usr/include')
85
+
86
+ unless find_header('libxslt/xslt.h', *HEADER_DIRS)
87
+ abort "need libxslt"
88
+ end
89
+ unless find_header('libexslt/exslt.h', *HEADER_DIRS)
51
90
  abort "need libxslt"
52
91
  end
53
92
 
@@ -3,22 +3,26 @@
3
3
  static VALUE native_parse_file(VALUE self, VALUE data, VALUE encoding)
4
4
  {
5
5
  xmlSAXHandlerPtr handler;
6
+ htmlDocPtr hdoc ;
6
7
  Data_Get_Struct(self, xmlSAXHandler, handler);
7
- htmlSAXParseFile( StringValuePtr(data),
8
- (const char *)StringValuePtr(encoding),
9
- (htmlSAXHandlerPtr)handler,
10
- (void *)self );
8
+ hdoc = htmlSAXParseFile( StringValuePtr(data),
9
+ (const char *)StringValuePtr(encoding),
10
+ (htmlSAXHandlerPtr)handler,
11
+ (void *)self );
12
+ xmlFreeDoc(hdoc);
11
13
  return data;
12
14
  }
13
15
 
14
16
  static VALUE native_parse_memory(VALUE self, VALUE data, VALUE encoding)
15
17
  {
16
18
  xmlSAXHandlerPtr handler;
19
+ htmlDocPtr hdoc ;
17
20
  Data_Get_Struct(self, xmlSAXHandler, handler);
18
- htmlSAXParseDoc( (xmlChar *)StringValuePtr(data),
19
- (const char *)StringValuePtr(encoding),
20
- (htmlSAXHandlerPtr)handler,
21
- (void *)self );
21
+ hdoc = htmlSAXParseDoc( (xmlChar *)StringValuePtr(data),
22
+ (const char *)StringValuePtr(encoding),
23
+ (htmlSAXHandlerPtr)handler,
24
+ (void *)self );
25
+ xmlFreeDoc(hdoc);
22
26
  return data;
23
27
  }
24
28
 
@@ -70,14 +70,20 @@ static VALUE internal_subset(VALUE self)
70
70
  * call-seq:
71
71
  * dup
72
72
  *
73
- * Copy this node
73
+ * Copy this node. An optional depth may be passed in, but it defaults
74
+ * to a deep copy. 0 is a shallow copy, 1 is a deep copy.
74
75
  */
75
- static VALUE duplicate_node(VALUE self)
76
+ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
76
77
  {
78
+ VALUE level;
79
+
80
+ if(rb_scan_args(argc, argv, "01", &level) == 0)
81
+ level = INT2NUM(1);
82
+
77
83
  xmlNodePtr node, dup;
78
84
  Data_Get_Struct(self, xmlNode, node);
79
85
 
80
- dup = xmlCopyNode(node, 1);
86
+ dup = xmlCopyNode(node, NUM2INT(level));
81
87
  if(dup == NULL) return Qnil;
82
88
  dup->doc = node->doc;
83
89
  assert(node->parent);
@@ -150,12 +156,7 @@ static VALUE previous_sibling(VALUE self)
150
156
  return Nokogiri_wrap_xml_node(sibling);
151
157
  }
152
158
 
153
- /*
154
- * call-seq:
155
- * replace(new_node)
156
- *
157
- * replace node with the new node in the document.
158
- */
159
+ /* :nodoc: */
159
160
  static VALUE replace(VALUE self, VALUE _new_node)
160
161
  {
161
162
  xmlNodePtr node, new_node;
@@ -338,18 +339,20 @@ static VALUE get_content(VALUE self)
338
339
 
339
340
  /*
340
341
  * call-seq:
341
- * parent=(parent_node)
342
+ * add_child(node)
342
343
  *
343
- * Set the parent Node for this Node
344
+ * Add +node+ as a child of this node. Returns the new child node.
344
345
  */
345
- static VALUE set_parent(VALUE self, VALUE parent_node)
346
+ static VALUE add_child(VALUE self, VALUE child)
346
347
  {
347
- xmlNodePtr node, parent;
348
- Data_Get_Struct(self, xmlNode, node);
349
- Data_Get_Struct(parent_node, xmlNode, parent);
348
+ xmlNodePtr node, parent, new_child;
349
+ Data_Get_Struct(child, xmlNode, node);
350
+ Data_Get_Struct(self, xmlNode, parent);
350
351
 
351
- xmlAddChild(parent, node);
352
- return parent_node;
352
+ if(!(new_child = xmlAddChild(parent, node)))
353
+ rb_raise(rb_eRuntimeError, "Could not add new child");
354
+
355
+ return Nokogiri_wrap_xml_node(new_child);
353
356
  }
354
357
 
355
358
  /*
@@ -443,13 +446,20 @@ static VALUE add_next_sibling(VALUE self, VALUE rb_node)
443
446
  static VALUE add_previous_sibling(VALUE self, VALUE rb_node)
444
447
  {
445
448
  xmlNodePtr node, new_sibling;
449
+ Check_Type(rb_node, T_DATA);
450
+
446
451
  Data_Get_Struct(self, xmlNode, node);
447
452
  Data_Get_Struct(rb_node, xmlNode, new_sibling);
448
- xmlAddPrevSibling(node, new_sibling);
453
+
454
+ if(!(new_sibling = xmlAddPrevSibling(node, new_sibling)))
455
+ rb_raise(rb_eRuntimeError, "Could not add previous sibling");
449
456
 
450
457
  rb_funcall(rb_node, rb_intern("decorate!"), 0);
451
458
 
452
- return rb_node;
459
+ VALUE rb_new_sibling = Nokogiri_wrap_xml_node(new_sibling);
460
+ rb_funcall(rb_new_sibling, rb_intern("decorate!"), 0);
461
+
462
+ return rb_new_sibling;
453
463
  }
454
464
 
455
465
  /*
@@ -458,16 +468,21 @@ static VALUE add_previous_sibling(VALUE self, VALUE rb_node)
458
468
  *
459
469
  * Returns this node as XML
460
470
  */
461
- static VALUE to_xml(VALUE self)
471
+ static VALUE to_xml(int argc, VALUE *argv, VALUE self)
462
472
  {
463
473
  xmlBufferPtr buf ;
464
474
  xmlNodePtr node ;
465
- VALUE xml ;
475
+ VALUE xml, level;
476
+
477
+ if(rb_scan_args(argc, argv, "01", &level) == 0)
478
+ level = INT2NUM(1);
479
+
480
+ Check_Type(level, T_FIXNUM);
466
481
 
467
482
  Data_Get_Struct(self, xmlNode, node);
468
483
 
469
484
  buf = xmlBufferCreate() ;
470
- xmlNodeDump(buf, node->doc, node, 2, 1);
485
+ xmlNodeDump(buf, node->doc, node, 2, NUM2INT(level));
471
486
  xml = rb_str_new2((char*)buf->content);
472
487
  xmlBufferFree(buf);
473
488
  return xml ;
@@ -646,12 +661,11 @@ void init_xml_node()
646
661
 
647
662
  rb_define_method(klass, "name", get_name, 0);
648
663
  rb_define_method(klass, "name=", set_name, 1);
649
- rb_define_method(klass, "parent=", set_parent, 1);
664
+ rb_define_method(klass, "add_child", add_child, 1);
650
665
  rb_define_method(klass, "parent", get_parent, 0);
651
666
  rb_define_method(klass, "child", child, 0);
652
667
  rb_define_method(klass, "next_sibling", next_sibling, 0);
653
668
  rb_define_method(klass, "previous_sibling", previous_sibling, 0);
654
- rb_define_method(klass, "replace", replace, 1);
655
669
  rb_define_method(klass, "type", type, 0);
656
670
  rb_define_method(klass, "content", get_content, 0);
657
671
  rb_define_method(klass, "path", path, 0);
@@ -664,12 +678,13 @@ void init_xml_node()
664
678
  rb_define_method(klass, "add_previous_sibling", add_previous_sibling, 1);
665
679
  rb_define_method(klass, "add_next_sibling", add_next_sibling, 1);
666
680
  rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
667
- rb_define_method(klass, "to_xml", to_xml, 0);
668
- rb_define_method(klass, "dup", duplicate_node, 0);
681
+ rb_define_method(klass, "to_xml", to_xml, -1);
682
+ rb_define_method(klass, "dup", duplicate_node, -1);
669
683
  rb_define_method(klass, "unlink", unlink_node, 0);
670
684
  rb_define_method(klass, "internal_subset", internal_subset, 0);
671
685
  rb_define_method(klass, "pointer_id", pointer_id, 0);
672
686
 
687
+ rb_define_private_method(klass, "replace_with_node", replace, 1);
673
688
  rb_define_private_method(klass, "native_content=", set_content, 1);
674
689
  rb_define_private_method(klass, "get", get, 1);
675
690
  }
@@ -28,6 +28,9 @@ static VALUE push(VALUE self, VALUE rb_node)
28
28
  xmlNodeSetPtr node_set;
29
29
  xmlNodePtr node;
30
30
 
31
+ if(! rb_funcall(rb_node, rb_intern("is_a?"), 1, cNokogiriXmlNode))
32
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
33
+
31
34
  Data_Get_Struct(self, xmlNodeSet, node_set);
32
35
  Data_Get_Struct(rb_node, xmlNode, node);
33
36
  xmlXPathNodeSetAdd(node_set, node);
@@ -42,6 +42,7 @@ static VALUE native_parse_io(VALUE self, VALUE io, VALUE encoding)
42
42
  enc
43
43
  );
44
44
  xmlParseDocument(sax_ctx);
45
+ xmlFreeParserCtxt(sax_ctx);
45
46
  return io;
46
47
  }
47
48
 
@@ -25,18 +25,132 @@ static VALUE register_ns(VALUE self, VALUE prefix, VALUE uri)
25
25
  return self;
26
26
  }
27
27
 
28
+ static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
29
+ {
30
+ VALUE xpath_handler = Qnil;
31
+ xmlXPathObjectPtr obj;
32
+
33
+ assert(ctx);
34
+ assert(ctx->context);
35
+ assert(ctx->context->userData);
36
+ assert(ctx->context->doc);
37
+ assert(ctx->context->doc->_private);
38
+
39
+ xpath_handler = (VALUE)(ctx->context->userData);
40
+
41
+ VALUE * argv = (VALUE *)calloc((unsigned int)nargs, sizeof(VALUE));
42
+ VALUE doc = (VALUE)ctx->context->doc->_private;
43
+
44
+ int i = nargs - 1;
45
+ do {
46
+ obj = valuePop(ctx);
47
+ switch(obj->type) {
48
+ case XPATH_STRING:
49
+ argv[i] = rb_str_new2((char *)obj->stringval);
50
+ break;
51
+ case XPATH_BOOLEAN:
52
+ argv[i] = obj->boolval == 1 ? Qtrue : Qfalse;
53
+ break;
54
+ case XPATH_NUMBER:
55
+ argv[i] = rb_float_new(obj->floatval);
56
+ break;
57
+ case XPATH_NODESET:
58
+ argv[i] = Nokogiri_wrap_xml_node_set(obj->nodesetval);
59
+ break;
60
+ default:
61
+ argv[i] = rb_str_new2((char *)xmlXPathCastToString(obj));
62
+ }
63
+ xmlXPathFreeNodeSetList(obj);
64
+ } while(i-- > 0);
65
+
66
+ VALUE result = rb_funcall2(
67
+ xpath_handler,
68
+ rb_intern((const char *)ctx->context->function),
69
+ nargs,
70
+ argv
71
+ );
72
+ free(argv);
73
+
74
+ VALUE node_set = Qnil;
75
+ xmlNodeSetPtr xml_node_set = NULL;
76
+
77
+ switch(TYPE(result)) {
78
+ case T_FLOAT:
79
+ case T_BIGNUM:
80
+ case T_FIXNUM:
81
+ xmlXPathReturnNumber(ctx, NUM2DBL(result));
82
+ break;
83
+ case T_STRING:
84
+ xmlXPathReturnString(
85
+ ctx,
86
+ xmlXPathWrapCString(StringValuePtr(result))
87
+ );
88
+ break;
89
+ case T_TRUE:
90
+ xmlXPathReturnTrue(ctx);
91
+ break;
92
+ case T_FALSE:
93
+ xmlXPathReturnFalse(ctx);
94
+ break;
95
+ case T_NIL:
96
+ break;
97
+ case T_ARRAY:
98
+ node_set = rb_funcall(
99
+ cNokogiriXmlNodeSet,
100
+ rb_intern("new"),
101
+ 2,
102
+ doc,
103
+ result
104
+ );
105
+ Data_Get_Struct(node_set, xmlNodeSet, xml_node_set);
106
+ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
107
+ break;
108
+ case T_DATA:
109
+ if(rb_funcall(result, rb_intern("is_a?"), 1, cNokogiriXmlNodeSet)) {
110
+ Data_Get_Struct(result, xmlNodeSet, xml_node_set);
111
+ // Copy the node set, otherwise it will get GC'd.
112
+ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
113
+ break;
114
+ }
115
+ default:
116
+ rb_raise(rb_eRuntimeError, "Invalid return type");
117
+ }
118
+ }
119
+
120
+ static xmlXPathFunction lookup( void *ctx,
121
+ const xmlChar * name,
122
+ const xmlChar* ns_uri )
123
+ {
124
+ VALUE xpath_handler = (VALUE)ctx;
125
+ if(rb_respond_to(xpath_handler, rb_intern((const char *)name)))
126
+ return ruby_funcall;
127
+
128
+ return NULL;
129
+ }
130
+
28
131
  /*
29
132
  * call-seq:
30
133
  * evaluate(search_path)
31
134
  *
32
135
  * Evaluate the +search_path+ returning an XML::XPath object.
33
136
  */
34
- static VALUE evaluate(VALUE self, VALUE search_path)
137
+ static VALUE evaluate(int argc, VALUE *argv, VALUE self)
35
138
  {
139
+ VALUE search_path, xpath_handler;
36
140
  xmlXPathContextPtr ctx;
37
141
  Data_Get_Struct(self, xmlXPathContext, ctx);
38
142
 
143
+ if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1)
144
+ xpath_handler = Qnil;
145
+
39
146
  xmlChar* query = (xmlChar *)StringValuePtr(search_path);
147
+
148
+ if(Qnil != xpath_handler) {
149
+ // FIXME: not sure if this is the correct place to shove private data.
150
+ ctx->userData = (void *)xpath_handler;
151
+ xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler);
152
+ }
153
+
40
154
  xmlXPathObjectPtr xpath = xmlXPathEvalExpression(query, ctx);
41
155
  if(xpath == NULL) {
42
156
  VALUE xpath = rb_const_get(mNokogiriXml, rb_intern("XPath"));
@@ -72,8 +186,10 @@ static VALUE new(VALUE klass, VALUE nodeobj)
72
186
  Data_Get_Struct(nodeobj, xmlNode, node);
73
187
 
74
188
  xmlXPathContextPtr ctx = xmlXPathNewContext(node->doc);
75
- ctx->node = node ;
76
- return Data_Wrap_Struct(klass, 0, deallocate, ctx);
189
+ ctx->node = node;
190
+ VALUE self = Data_Wrap_Struct(klass, 0, deallocate, ctx);
191
+ //rb_iv_set(self, "@xpath_handler", Qnil);
192
+ return self;
77
193
  }
78
194
 
79
195
  VALUE cNokogiriXmlXpathContext;
@@ -94,6 +210,6 @@ void init_xml_xpath_context(void)
94
210
  cNokogiriXmlXpathContext = klass;
95
211
 
96
212
  rb_define_singleton_method(klass, "new", new, 1);
97
- rb_define_method(klass, "evaluate", evaluate, 1);
213
+ rb_define_method(klass, "evaluate", evaluate, -1);
98
214
  rb_define_method(klass, "register_ns", register_ns, 2);
99
215
  }