nokogiri 1.2.1 → 1.2.2
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.
- data/.autotest +15 -0
- data/{History.ja.txt → CHANGELOG.ja.rdoc} +30 -2
- data/{History.txt → CHANGELOG.rdoc} +28 -2
- data/Manifest.txt +13 -7
- data/{README.ja.txt → README.ja.rdoc} +3 -1
- data/{README.txt → README.rdoc} +7 -1
- data/Rakefile +8 -25
- data/ext/nokogiri/extconf.rb +4 -4
- data/ext/nokogiri/html_entity_lookup.c +30 -0
- data/ext/nokogiri/html_entity_lookup.h +8 -0
- data/ext/nokogiri/native.c +22 -0
- data/ext/nokogiri/native.h +27 -4
- data/ext/nokogiri/xml_document.c +31 -4
- data/ext/nokogiri/xml_document.h +11 -0
- data/ext/nokogiri/xml_document_fragment.c +1 -1
- data/ext/nokogiri/xml_node.c +71 -58
- data/ext/nokogiri/xml_node_set.c +26 -0
- data/ext/nokogiri/xml_reader.c +4 -2
- data/ext/nokogiri/xml_sax_parser.c +0 -37
- data/ext/nokogiri/xml_sax_push_parser.c +2 -2
- data/ext/nokogiri/xml_xpath_context.c +34 -7
- data/lib/nokogiri.rb +25 -0
- data/lib/nokogiri/css/generated_tokenizer.rb +2 -2
- data/lib/nokogiri/css/node.rb +2 -0
- data/lib/nokogiri/css/parser.rb +3 -2
- data/lib/nokogiri/html.rb +9 -52
- data/lib/nokogiri/html/document.rb +2 -0
- data/lib/nokogiri/html/entity_lookup.rb +11 -0
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml.rb +1 -2
- data/lib/nokogiri/xml/builder.rb +18 -5
- data/lib/nokogiri/xml/document.rb +15 -1
- data/lib/nokogiri/xml/fragment_handler.rb +34 -0
- data/lib/nokogiri/xml/node.rb +104 -29
- data/lib/nokogiri/xml/node_set.rb +12 -10
- data/lib/nokogiri/xml/sax/parser.rb +3 -3
- data/lib/xsd/xmlparser/nokogiri.rb +53 -0
- data/tasks/test.rb +7 -5
- data/test/css/test_nthiness.rb +1 -0
- data/test/css/test_parser.rb +1 -0
- data/test/css/test_tokenizer.rb +1 -0
- data/test/css/test_xpath_visitor.rb +1 -0
- data/test/helper.rb +4 -0
- data/test/hpricot/test_alter.rb +1 -0
- data/test/html/sax/test_parser.rb +13 -0
- data/test/html/test_builder.rb +21 -0
- data/test/html/test_document.rb +36 -0
- data/test/html/test_document_encoding.rb +46 -0
- data/test/html/test_named_characters.rb +14 -0
- data/test/html/test_node.rb +80 -0
- data/test/test_convert_xpath.rb +1 -0
- data/test/test_css_cache.rb +1 -0
- data/test/test_nokogiri.rb +8 -0
- data/test/xml/sax/test_parser.rb +6 -0
- data/test/xml/sax/test_push_parser.rb +1 -0
- data/test/xml/test_builder.rb +9 -0
- data/test/xml/test_cdata.rb +1 -0
- data/test/xml/test_comment.rb +1 -0
- data/test/xml/test_document.rb +58 -0
- data/test/xml/test_document_encoding.rb +15 -14
- data/test/xml/test_document_fragment.rb +6 -0
- data/test/xml/test_dtd.rb +1 -0
- data/test/xml/test_dtd_encoding.rb +1 -0
- data/test/xml/test_entity_reference.rb +1 -0
- data/test/xml/test_node.rb +52 -4
- data/test/xml/test_node_encoding.rb +1 -0
- data/test/xml/test_node_set.rb +21 -1
- data/test/xml/test_processing_instruction.rb +1 -0
- data/test/xml/test_reader_encoding.rb +1 -0
- data/test/xml/test_unparented_node.rb +381 -0
- data/test/xml/test_xpath.rb +1 -0
- metadata +34 -16
- data/lib/nokogiri/xml/after_handler.rb +0 -18
- data/lib/nokogiri/xml/before_handler.rb +0 -33
- data/vendor/hoe.rb +0 -1020
data/ext/nokogiri/xml_document.h
CHANGED
@@ -3,8 +3,19 @@
|
|
3
3
|
|
4
4
|
#include <native.h>
|
5
5
|
|
6
|
+
struct _nokogiriTuple {
|
7
|
+
xmlDocPtr doc;
|
8
|
+
xmlNodeSetPtr unlinkedNodes;
|
9
|
+
};
|
10
|
+
typedef struct _nokogiriTuple nokogiriTuple;
|
11
|
+
typedef nokogiriTuple * nokogiriTuplePtr;
|
12
|
+
|
6
13
|
void init_xml_document();
|
7
14
|
VALUE Nokogiri_wrap_xml_document(VALUE klass, xmlDocPtr doc);
|
8
15
|
|
16
|
+
#define DOC_RUBY_OBJECT_TEST(x) ((nokogiriTuplePtr)(x->_private))
|
17
|
+
#define DOC_RUBY_OBJECT(x) ((VALUE)((nokogiriTuplePtr)(x->_private))->doc)
|
18
|
+
#define DOC_UNLINKED_NODE_SET(x) ((xmlNodeSetPtr)((nokogiriTuplePtr)(x->_private))->unlinkedNodes)
|
19
|
+
|
9
20
|
extern VALUE cNokogiriXmlDocument ;
|
10
21
|
#endif
|
@@ -11,7 +11,7 @@ static VALUE new(VALUE klass, VALUE doc)
|
|
11
11
|
xmlDocPtr xml_doc;
|
12
12
|
Data_Get_Struct(doc, xmlDoc, xml_doc);
|
13
13
|
|
14
|
-
xmlNodePtr node = xmlNewDocFragment(xml_doc);
|
14
|
+
xmlNodePtr node = xmlNewDocFragment(xml_doc->doc);
|
15
15
|
|
16
16
|
VALUE rb_node = Nokogiri_wrap_xml_node(node);
|
17
17
|
|
data/ext/nokogiri/xml_node.c
CHANGED
@@ -10,6 +10,55 @@ static void debug_node_dealloc(xmlNodePtr x)
|
|
10
10
|
# define debug_node_dealloc 0
|
11
11
|
#endif
|
12
12
|
|
13
|
+
/* :nodoc: */
|
14
|
+
typedef xmlNodePtr (*node_other_func)(xmlNodePtr, xmlNodePtr);
|
15
|
+
|
16
|
+
/* :nodoc: */
|
17
|
+
static VALUE reparent_node_with(VALUE node_obj, VALUE other_obj, node_other_func func)
|
18
|
+
{
|
19
|
+
VALUE reparented_obj ;
|
20
|
+
xmlNodePtr node, other, reparented ;
|
21
|
+
|
22
|
+
Data_Get_Struct(node_obj, xmlNode, node);
|
23
|
+
Data_Get_Struct(other_obj, xmlNode, other);
|
24
|
+
|
25
|
+
if (node->doc == other->doc) {
|
26
|
+
xmlUnlinkNode(node) ;
|
27
|
+
if(!(reparented = (*func)(other, node))) {
|
28
|
+
rb_raise(rb_eRuntimeError, "Could not reparent node (1)");
|
29
|
+
}
|
30
|
+
|
31
|
+
} else {
|
32
|
+
xmlNodePtr duped_node ;
|
33
|
+
// recursively copy to the new document
|
34
|
+
if (!(duped_node = xmlDocCopyNode(node, other->doc, 1))) {
|
35
|
+
rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
|
36
|
+
}
|
37
|
+
if(!(reparented = (*func)(other, duped_node))) {
|
38
|
+
rb_raise(rb_eRuntimeError, "Could not reparent node (2)");
|
39
|
+
}
|
40
|
+
xmlUnlinkNode(node);
|
41
|
+
NOKOGIRI_ROOT_NODE(node);
|
42
|
+
}
|
43
|
+
|
44
|
+
// the child was a text node that was coalesced. we need to have the object
|
45
|
+
// point at SOMETHING, or we'll totally bomb out.
|
46
|
+
if (reparented != node) {
|
47
|
+
DATA_PTR(node_obj) = reparented ;
|
48
|
+
}
|
49
|
+
|
50
|
+
// Make sure that our reparented node has the correct namespaces
|
51
|
+
if(reparented->doc != reparented->parent)
|
52
|
+
reparented->ns = reparented->parent->ns;
|
53
|
+
|
54
|
+
reparented_obj = Nokogiri_wrap_xml_node(reparented);
|
55
|
+
|
56
|
+
rb_funcall(reparented_obj, rb_intern("decorate!"), 0);
|
57
|
+
|
58
|
+
return reparented_obj ;
|
59
|
+
}
|
60
|
+
|
61
|
+
|
13
62
|
/*
|
14
63
|
* call-seq:
|
15
64
|
* pointer_id
|
@@ -101,6 +150,7 @@ static VALUE unlink_node(VALUE self)
|
|
101
150
|
xmlNodePtr node;
|
102
151
|
Data_Get_Struct(self, xmlNode, node);
|
103
152
|
xmlUnlinkNode(node);
|
153
|
+
NOKOGIRI_ROOT_NODE(node);
|
104
154
|
return self;
|
105
155
|
}
|
106
156
|
|
@@ -208,12 +258,9 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
|
|
208
258
|
xmlNodePtr node;
|
209
259
|
Data_Get_Struct(self, xmlNode, node);
|
210
260
|
|
211
|
-
xmlChar *
|
261
|
+
xmlSetProp(node, (xmlChar *)StringValuePtr(property),
|
212
262
|
(xmlChar *)StringValuePtr(value));
|
213
263
|
|
214
|
-
xmlSetProp(node, (xmlChar *)StringValuePtr(property), buffer);
|
215
|
-
xmlFree(buffer);
|
216
|
-
|
217
264
|
return value;
|
218
265
|
}
|
219
266
|
|
@@ -371,21 +418,7 @@ static VALUE get_content(VALUE self)
|
|
371
418
|
*/
|
372
419
|
static VALUE add_child(VALUE self, VALUE child)
|
373
420
|
{
|
374
|
-
|
375
|
-
Data_Get_Struct(child, xmlNode, node);
|
376
|
-
Data_Get_Struct(self, xmlNode, parent);
|
377
|
-
|
378
|
-
xmlUnlinkNode(node) ;
|
379
|
-
|
380
|
-
if(!(new_child = xmlAddChild(parent, node)))
|
381
|
-
rb_raise(rb_eRuntimeError, "Could not add new child");
|
382
|
-
|
383
|
-
// the child was a text node that was coalesced. we need to have the object
|
384
|
-
// point at SOMETHING, or we'll totally bomb out.
|
385
|
-
if (new_child != node)
|
386
|
-
DATA_PTR(child) = new_child ;
|
387
|
-
|
388
|
-
return Nokogiri_wrap_xml_node(new_child);
|
421
|
+
return reparent_node_with(child, self, xmlAddChild);
|
389
422
|
}
|
390
423
|
|
391
424
|
/*
|
@@ -460,20 +493,7 @@ static VALUE path(VALUE self)
|
|
460
493
|
*/
|
461
494
|
static VALUE add_next_sibling(VALUE self, VALUE rb_node)
|
462
495
|
{
|
463
|
-
|
464
|
-
Data_Get_Struct(self, xmlNode, node);
|
465
|
-
Data_Get_Struct(rb_node, xmlNode, _new_sibling);
|
466
|
-
|
467
|
-
if(!(new_sibling = xmlAddNextSibling(node, _new_sibling)))
|
468
|
-
rb_raise(rb_eRuntimeError, "Could not add next sibling");
|
469
|
-
|
470
|
-
// the sibling was a text node that was coalesced. we need to have the object
|
471
|
-
// point at SOMETHING, or we'll totally bomb out.
|
472
|
-
if(new_sibling != _new_sibling) DATA_PTR(rb_node) = new_sibling;
|
473
|
-
|
474
|
-
rb_funcall(rb_node, rb_intern("decorate!"), 0);
|
475
|
-
|
476
|
-
return rb_node;
|
496
|
+
return reparent_node_with(rb_node, self, xmlAddNextSibling) ;
|
477
497
|
}
|
478
498
|
|
479
499
|
/*
|
@@ -484,22 +504,7 @@ static VALUE add_next_sibling(VALUE self, VALUE rb_node)
|
|
484
504
|
*/
|
485
505
|
static VALUE add_previous_sibling(VALUE self, VALUE rb_node)
|
486
506
|
{
|
487
|
-
|
488
|
-
Check_Type(rb_node, T_DATA);
|
489
|
-
|
490
|
-
Data_Get_Struct(self, xmlNode, node);
|
491
|
-
Data_Get_Struct(rb_node, xmlNode, sibling);
|
492
|
-
|
493
|
-
if(!(new_sibling = xmlAddPrevSibling(node, sibling)))
|
494
|
-
rb_raise(rb_eRuntimeError, "Could not add previous sibling");
|
495
|
-
|
496
|
-
// the sibling was a text node that was coalesced. we need to have the object
|
497
|
-
// point at SOMETHING, or we'll totally bomb out.
|
498
|
-
if(sibling != new_sibling) DATA_PTR(rb_node) = new_sibling;
|
499
|
-
|
500
|
-
rb_funcall(rb_node, rb_intern("decorate!"), 0);
|
501
|
-
|
502
|
-
return rb_node;
|
507
|
+
return reparent_node_with(rb_node, self, xmlAddPrevSibling) ;
|
503
508
|
}
|
504
509
|
|
505
510
|
/*
|
@@ -560,12 +565,14 @@ static VALUE add_namespace(VALUE self, VALUE prefix, VALUE href)
|
|
560
565
|
|
561
566
|
if(NULL == ns) return self;
|
562
567
|
|
568
|
+
/*
|
563
569
|
xmlNewNsProp(
|
564
570
|
node,
|
565
571
|
ns,
|
566
572
|
(const xmlChar *)StringValuePtr(href),
|
567
573
|
(const xmlChar *)StringValuePtr(prefix)
|
568
574
|
);
|
575
|
+
*/
|
569
576
|
|
570
577
|
return self;
|
571
578
|
}
|
@@ -617,16 +624,18 @@ static VALUE dump_html(VALUE self)
|
|
617
624
|
VALUE Nokogiri_wrap_xml_node(xmlNodePtr node)
|
618
625
|
{
|
619
626
|
assert(node);
|
620
|
-
assert(node->doc);
|
621
|
-
assert(node->doc->_private);
|
622
627
|
|
623
628
|
VALUE index = INT2NUM((int)node);
|
624
|
-
VALUE document =
|
625
|
-
|
626
|
-
VALUE
|
627
|
-
|
628
|
-
|
629
|
-
|
629
|
+
VALUE document = Qnil ;
|
630
|
+
VALUE node_cache = Qnil ;
|
631
|
+
VALUE rb_node = Qnil ;
|
632
|
+
|
633
|
+
if (DOC_RUBY_OBJECT_TEST(node->doc) && DOC_RUBY_OBJECT(node->doc)) {
|
634
|
+
document = DOC_RUBY_OBJECT(node->doc);
|
635
|
+
node_cache = rb_funcall(document, rb_intern("node_cache"), 0);
|
636
|
+
rb_node = rb_hash_aref(node_cache, index);
|
637
|
+
if(rb_node != Qnil) return rb_node;
|
638
|
+
}
|
630
639
|
|
631
640
|
switch(node->type)
|
632
641
|
{
|
@@ -672,11 +681,15 @@ VALUE Nokogiri_wrap_xml_node(xmlNodePtr node)
|
|
672
681
|
klass = rb_const_get(mNokogiriXml, rb_intern("DTD"));
|
673
682
|
rb_node = Data_Wrap_Struct(klass, 0, debug_node_dealloc, node) ;
|
674
683
|
break;
|
684
|
+
case XML_DOCUMENT_NODE:
|
685
|
+
return DOC_RUBY_OBJECT(node->doc);
|
686
|
+
case XML_HTML_DOCUMENT_NODE:
|
687
|
+
return DOC_RUBY_OBJECT(node->doc);
|
675
688
|
default:
|
676
689
|
rb_node = Data_Wrap_Struct(cNokogiriXmlNode, 0, debug_node_dealloc, node) ;
|
677
690
|
}
|
678
691
|
|
679
|
-
rb_hash_aset(node_cache, index, rb_node);
|
692
|
+
if (node_cache != Qnil) rb_hash_aset(node_cache, index, rb_node);
|
680
693
|
rb_iv_set(rb_node, "@document", document);
|
681
694
|
rb_funcall(rb_node, rb_intern("decorate!"), 0);
|
682
695
|
return rb_node ;
|
data/ext/nokogiri/xml_node_set.c
CHANGED
@@ -58,6 +58,31 @@ static VALUE index_at(VALUE self, VALUE number)
|
|
58
58
|
return Nokogiri_wrap_xml_node(node_set->nodeTab[i]);
|
59
59
|
}
|
60
60
|
|
61
|
+
/*
|
62
|
+
* call-seq:
|
63
|
+
* unlink
|
64
|
+
*
|
65
|
+
* Unlink this NodeSet and all Node objects it contains from their current context.
|
66
|
+
*/
|
67
|
+
static VALUE unlink_nodeset(VALUE self)
|
68
|
+
{
|
69
|
+
xmlNodeSetPtr node_set;
|
70
|
+
int j, nodeNr ;
|
71
|
+
|
72
|
+
Data_Get_Struct(self, xmlNodeSet, node_set);
|
73
|
+
nodeNr = node_set->nodeNr ;
|
74
|
+
for (j = 0 ; j < nodeNr ; j++) {
|
75
|
+
VALUE node ;
|
76
|
+
xmlNodePtr node_ptr;
|
77
|
+
node = Nokogiri_wrap_xml_node(node_set->nodeTab[j]);
|
78
|
+
rb_funcall(node, rb_intern("unlink"), 0); /* modifies the C struct out from under the object */
|
79
|
+
Data_Get_Struct(node, xmlNode, node_ptr);
|
80
|
+
node_set->nodeTab[j] = node_ptr ;
|
81
|
+
}
|
82
|
+
return self ;
|
83
|
+
}
|
84
|
+
|
85
|
+
|
61
86
|
static void deallocate(xmlNodeSetPtr node_set)
|
62
87
|
{
|
63
88
|
/*
|
@@ -119,4 +144,5 @@ void init_xml_node_set(void)
|
|
119
144
|
rb_define_method(klass, "length", length, 0);
|
120
145
|
rb_define_method(klass, "[]", index_at, 1);
|
121
146
|
rb_define_method(klass, "push", push, 1);
|
147
|
+
rb_define_method(klass, "unlink", unlink_nodeset, 0);
|
122
148
|
}
|
data/ext/nokogiri/xml_reader.c
CHANGED
@@ -126,10 +126,12 @@ static VALUE attribute_nodes(VALUE self)
|
|
126
126
|
// FIXME I'm not sure if this is correct..... I don't really like pointing
|
127
127
|
// at this document, but I have to because of the assertions in
|
128
128
|
// the node wrapping code.
|
129
|
-
if(!ptr->doc
|
129
|
+
if(! DOC_RUBY_OBJECT_TEST(ptr->doc)) {
|
130
130
|
VALUE rb_doc = Data_Wrap_Struct(cNokogiriXmlDocument, 0, 0, ptr->doc);
|
131
|
+
ptr->doc->_private = malloc(sizeof(nokogiriTuple));
|
131
132
|
rb_iv_set(rb_doc, "@decorators", Qnil);
|
132
|
-
ptr->doc->_private = (void *)rb_doc;
|
133
|
+
((nokogiriTuplePtr)(ptr->doc->_private))->doc = (void *)rb_doc;
|
134
|
+
((nokogiriTuplePtr)(ptr->doc->_private))->unlinkedNodes = xmlXPathNodeSetCreate(NULL);
|
133
135
|
}
|
134
136
|
VALUE enc = rb_iv_get(self, "@encoding");
|
135
137
|
|
@@ -129,43 +129,6 @@ static void comment_func(void * ctx, const xmlChar * value)
|
|
129
129
|
rb_funcall(doc, rb_intern("comment"), 1, str);
|
130
130
|
}
|
131
131
|
|
132
|
-
#ifdef XP_WIN
|
133
|
-
/*
|
134
|
-
* I srsly hate windows. it doesn't have vasprintf.
|
135
|
-
* This is stolen from here:
|
136
|
-
* http://eleves.ec-lille.fr/~couprieg/index.php?2008/06/17/39-first-issues-when-porting-an-application-on-windows-ce
|
137
|
-
* and slightly modified
|
138
|
-
*/
|
139
|
-
static inline int vasprintf(char **strp, const char *fmt, va_list ap) {
|
140
|
-
int n;
|
141
|
-
size_t size = 4096;
|
142
|
-
char *res, *np;
|
143
|
-
|
144
|
-
if ( (res = (char *) malloc(size)) == NULL )
|
145
|
-
return -1;
|
146
|
-
|
147
|
-
while (1) {
|
148
|
-
n = vsnprintf (res, size, fmt, ap);
|
149
|
-
/* If that worked, return the string. */
|
150
|
-
if (n > -1 && n < size) {
|
151
|
-
*strp = res;
|
152
|
-
return n;
|
153
|
-
}
|
154
|
-
|
155
|
-
/* Else try again with more space. */
|
156
|
-
if (n == -1)
|
157
|
-
size *= 2; /* twice the old size */
|
158
|
-
|
159
|
-
if ( (np = (char *) realloc(res, size)) == NULL ) {
|
160
|
-
free(res);
|
161
|
-
return -1;
|
162
|
-
} else {
|
163
|
-
res = np;
|
164
|
-
}
|
165
|
-
}
|
166
|
-
}
|
167
|
-
#endif
|
168
|
-
|
169
132
|
static void warning_func(void * ctx, const char *msg, ...)
|
170
133
|
{
|
171
134
|
VALUE self = (VALUE)ctx;
|
@@ -34,12 +34,12 @@ static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
|
|
34
34
|
assert(ctx->context);
|
35
35
|
assert(ctx->context->userData);
|
36
36
|
assert(ctx->context->doc);
|
37
|
-
assert(ctx->context->doc
|
37
|
+
assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc));
|
38
38
|
|
39
39
|
xpath_handler = (VALUE)(ctx->context->userData);
|
40
40
|
|
41
41
|
VALUE * argv = (VALUE *)calloc((unsigned int)nargs, sizeof(VALUE));
|
42
|
-
VALUE doc = (
|
42
|
+
VALUE doc = DOC_RUBY_OBJECT(ctx->context->doc);
|
43
43
|
|
44
44
|
int i = nargs - 1;
|
45
45
|
do {
|
@@ -130,6 +130,28 @@ static xmlXPathFunction lookup( void *ctx,
|
|
130
130
|
return NULL;
|
131
131
|
}
|
132
132
|
|
133
|
+
static void xpath_exception_handler(void * ctx, xmlErrorPtr error)
|
134
|
+
{
|
135
|
+
VALUE xpath = rb_const_get(mNokogiriXml, rb_intern("XPath"));
|
136
|
+
VALUE klass = rb_const_get(xpath, rb_intern("SyntaxError"));
|
137
|
+
|
138
|
+
rb_funcall(rb_mKernel, rb_intern("raise"), 1,
|
139
|
+
Nokogiri_wrap_xml_syntax_error(klass, error)
|
140
|
+
);
|
141
|
+
}
|
142
|
+
|
143
|
+
static void xpath_generic_exception_handler(void * ctx, const char *msg, ...)
|
144
|
+
{
|
145
|
+
char * message;
|
146
|
+
|
147
|
+
va_list args;
|
148
|
+
va_start(args, msg);
|
149
|
+
vasprintf(&message, msg, args);
|
150
|
+
va_end(args);
|
151
|
+
|
152
|
+
rb_raise(rb_eRuntimeError, message);
|
153
|
+
}
|
154
|
+
|
133
155
|
/*
|
134
156
|
* call-seq:
|
135
157
|
* evaluate(search_path)
|
@@ -141,7 +163,6 @@ static VALUE evaluate(int argc, VALUE *argv, VALUE self)
|
|
141
163
|
VALUE search_path, xpath_handler;
|
142
164
|
xmlXPathContextPtr ctx;
|
143
165
|
Data_Get_Struct(self, xmlXPathContext, ctx);
|
144
|
-
VALUE error_list = rb_ary_new();
|
145
166
|
|
146
167
|
if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1)
|
147
168
|
xpath_handler = Qnil;
|
@@ -155,9 +176,15 @@ static VALUE evaluate(int argc, VALUE *argv, VALUE self)
|
|
155
176
|
}
|
156
177
|
|
157
178
|
xmlResetLastError();
|
158
|
-
xmlSetStructuredErrorFunc(
|
179
|
+
xmlSetStructuredErrorFunc(NULL, xpath_exception_handler);
|
180
|
+
|
181
|
+
// For some reason, xmlXPathEvalExpression will blow up with a generic error
|
182
|
+
// when there is a non existent function.
|
183
|
+
xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
|
184
|
+
|
159
185
|
xmlXPathObjectPtr xpath = xmlXPathEvalExpression(query, ctx);
|
160
186
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
187
|
+
xmlSetGenericErrorFunc(NULL, NULL);
|
161
188
|
|
162
189
|
if(xpath == NULL) {
|
163
190
|
VALUE xpath = rb_const_get(mNokogiriXml, rb_intern("XPath"));
|
@@ -172,13 +199,13 @@ static VALUE evaluate(int argc, VALUE *argv, VALUE self)
|
|
172
199
|
VALUE xpath_object = Nokogiri_wrap_xml_xpath(xpath);
|
173
200
|
|
174
201
|
assert(ctx->doc);
|
175
|
-
assert(ctx->doc
|
202
|
+
assert(DOC_RUBY_OBJECT_TEST(ctx->doc));
|
176
203
|
|
177
204
|
rb_funcall( xpath_object,
|
178
205
|
rb_intern("document="),
|
179
206
|
1,
|
180
|
-
(
|
181
|
-
|
207
|
+
DOC_RUBY_OBJECT(ctx->doc)
|
208
|
+
);
|
182
209
|
return xpath_object;
|
183
210
|
}
|
184
211
|
|
data/lib/nokogiri.rb
CHANGED
@@ -15,6 +15,31 @@ require 'nokogiri/css'
|
|
15
15
|
require 'nokogiri/html/builder'
|
16
16
|
require 'nokogiri/hpricot'
|
17
17
|
|
18
|
+
# Nokogiri parses and searches XML/HTML very quickly, and also has
|
19
|
+
# correctly implemented CSS3 selector support as well as XPath support.
|
20
|
+
#
|
21
|
+
# Parsing a document returns either a Nokogiri::XML::Document, or a
|
22
|
+
# Nokogiri::HTML::Document depending on the kind of document you parse.
|
23
|
+
#
|
24
|
+
# Here is an example:
|
25
|
+
#
|
26
|
+
# require 'nokogiri'
|
27
|
+
# require 'open-uri'
|
28
|
+
#
|
29
|
+
# # Get a Nokogiri::HTML:Document for the page we’re interested in...
|
30
|
+
#
|
31
|
+
# doc = Nokogiri::HTML(open('http://www.google.com/search?q=tenderlove'))
|
32
|
+
#
|
33
|
+
# # Do funky things with it using Nokogiri::XML::Node methods...
|
34
|
+
#
|
35
|
+
# ####
|
36
|
+
# # Search for nodes by css
|
37
|
+
# doc.css('h3.r a.l').each do |link|
|
38
|
+
# puts link.content
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# See Nokogiri::XML::Node#css for more information about CSS searching.
|
42
|
+
# See Nokogiri::XML::Node#xpath for more information about XPath searching.
|
18
43
|
module Nokogiri
|
19
44
|
class << self
|
20
45
|
###
|