libxml-ruby 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +53 -0
- data/Rakefile +1 -0
- data/ext/libxml/build.log +4 -0
- data/ext/libxml/cbg.c +86 -86
- data/ext/libxml/libxml.c +878 -876
- data/ext/libxml/ruby_libxml.h +8 -4
- data/ext/libxml/ruby_xml_attr.c +36 -168
- data/ext/libxml/ruby_xml_attr.h +2 -4
- data/ext/libxml/ruby_xml_attr_decl.c +177 -0
- data/ext/libxml/ruby_xml_attr_decl.h +13 -0
- data/ext/libxml/ruby_xml_attributes.c +29 -20
- data/ext/libxml/ruby_xml_document.c +895 -898
- data/ext/libxml/ruby_xml_dtd.c +18 -1
- data/ext/libxml/ruby_xml_dtd.h +1 -0
- data/ext/libxml/ruby_xml_encoding.c +116 -0
- data/ext/libxml/ruby_xml_encoding.h +12 -0
- data/ext/libxml/ruby_xml_error.c +8 -2
- data/ext/libxml/ruby_xml_html_parser.c +53 -74
- data/ext/libxml/ruby_xml_html_parser.h +2 -3
- data/ext/libxml/ruby_xml_html_parser_context.c +145 -0
- data/ext/libxml/ruby_xml_html_parser_context.h +12 -0
- data/ext/libxml/ruby_xml_html_parser_options.c +48 -0
- data/ext/libxml/ruby_xml_html_parser_options.h +12 -0
- data/ext/libxml/ruby_xml_input_cbg.c +1 -1
- data/ext/libxml/ruby_xml_io.c +30 -0
- data/ext/libxml/ruby_xml_io.h +9 -0
- data/ext/libxml/ruby_xml_namespace.c +34 -16
- data/ext/libxml/ruby_xml_namespace.h +2 -2
- data/ext/libxml/ruby_xml_namespaces.c +6 -6
- data/ext/libxml/ruby_xml_node.c +1367 -1324
- data/ext/libxml/ruby_xml_node.h +2 -2
- data/ext/libxml/ruby_xml_parser.c +26 -78
- data/ext/libxml/ruby_xml_parser.h +1 -1
- data/ext/libxml/ruby_xml_parser_context.c +284 -13
- data/ext/libxml/ruby_xml_parser_context.h +1 -2
- data/ext/libxml/ruby_xml_parser_options.c +75 -0
- data/ext/libxml/ruby_xml_parser_options.h +14 -0
- data/ext/libxml/ruby_xml_reader.c +277 -183
- data/ext/libxml/ruby_xml_sax_parser.c +60 -57
- data/ext/libxml/ruby_xml_xpath_context.c +43 -8
- data/ext/libxml/ruby_xml_xpath_expression.c +6 -0
- data/ext/libxml/ruby_xml_xpath_object.c +107 -95
- data/ext/libxml/ruby_xml_xpath_object.h +9 -1
- data/ext/libxml/ruby_xml_xpointer.c +107 -107
- data/ext/libxml/version.h +2 -2
- data/ext/vc/libxml_ruby.vcproj +43 -3
- data/lib/libxml.rb +2 -3
- data/lib/libxml/attr.rb +71 -2
- data/lib/libxml/attr_decl.rb +81 -0
- data/lib/libxml/document.rb +78 -14
- data/lib/libxml/html_parser.rb +75 -42
- data/lib/libxml/node.rb +11 -0
- data/lib/libxml/parser.rb +106 -62
- data/lib/libxml/reader.rb +12 -0
- data/lib/libxml/sax_parser.rb +42 -52
- data/lib/libxml/xpath_object.rb +15 -0
- data/test/model/atom.xml +12 -12
- data/test/model/bands.xml +4 -4
- data/test/model/books.xml +146 -147
- data/test/model/merge_bug_data.xml +1 -1
- data/test/model/rubynet.xml +1 -0
- data/test/model/shiporder.rng +1 -1
- data/test/model/shiporder.xml +22 -22
- data/test/model/shiporder.xsd +30 -30
- data/test/model/xinclude.xml +1 -1
- data/test/{tc_node_attr.rb → tc_attr.rb} +1 -1
- data/test/tc_attr_decl.rb +131 -0
- data/test/tc_deprecated_require.rb +1 -3
- data/test/tc_document.rb +13 -3
- data/test/tc_document_write.rb +5 -5
- data/test/tc_dtd.rb +13 -5
- data/test/tc_html_parser.rb +14 -26
- data/test/tc_node_cdata.rb +1 -3
- data/test/tc_node_comment.rb +2 -4
- data/test/tc_node_edit.rb +2 -3
- data/test/tc_node_text.rb +35 -1
- data/test/tc_node_write.rb +3 -3
- data/test/tc_node_xlink.rb +2 -4
- data/test/tc_parser.rb +163 -70
- data/test/tc_parser_context.rb +103 -42
- data/test/tc_reader.rb +173 -45
- data/test/tc_relaxng.rb +2 -2
- data/test/tc_sax_parser.rb +48 -52
- data/test/tc_schema.rb +2 -2
- data/test/tc_xpath.rb +37 -6
- data/test/tc_xpath_context.rb +7 -1
- data/test/tc_xpath_expression.rb +1 -3
- data/test/tc_xpointer.rb +1 -3
- data/test/test_suite.rb +2 -3
- metadata +20 -13
- data/ext/libxml/ruby_xml_input.c +0 -329
- data/ext/libxml/ruby_xml_input.h +0 -20
- data/lib/libxml/parser_context.rb +0 -17
- data/lib/libxml/parser_options.rb +0 -25
- data/test/model/simple.xml +0 -7
- data/test/tc_input.rb +0 -13
- data/test/tc_well_formed.rb +0 -11
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: ruby_xml_sax_parser.c
|
1
|
+
/* $Id: ruby_xml_sax_parser.c 740 2009-01-23 04:03:11Z cfis $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
@@ -12,7 +12,7 @@
|
|
12
12
|
* in contrast to XML::Parser's tree based API and XML::Reader's stream
|
13
13
|
* based API.
|
14
14
|
*
|
15
|
-
*
|
15
|
+
* The XML::SaxParser API is fairly complex, not well standardized,
|
16
16
|
* and does not directly support validation making entity, namespace and
|
17
17
|
* base processing relatively hard.
|
18
18
|
*
|
@@ -30,49 +30,22 @@
|
|
30
30
|
* end
|
31
31
|
* end
|
32
32
|
*
|
33
|
-
* parser = XML::SaxParser.
|
33
|
+
* parser = XML::SaxParser.string(my_string)
|
34
34
|
* parser.callbacks = MyCallbacks.new
|
35
35
|
* parser.parse
|
36
|
+
*
|
37
|
+
* You can also parse strings (see XML::SaxParser.string) and
|
38
|
+
* io objects (see XML::SaxParser.io).
|
36
39
|
*/
|
37
40
|
|
38
41
|
VALUE cXMLSaxParser;
|
39
|
-
|
40
|
-
static ID INPUT_ATTR;
|
41
42
|
static ID CALLBACKS_ATTR;
|
43
|
+
static ID CONTEXT_ATTR;
|
42
44
|
|
43
45
|
|
44
46
|
/* ====== Parser =========== */
|
45
|
-
/*
|
46
|
-
* call-seq:
|
47
|
-
* sax_parser.initialize -> sax_parser
|
48
|
-
*
|
49
|
-
* Initiliazes instance of parser.
|
50
|
-
*/
|
51
|
-
static VALUE rxml_sax_parser_initialize(VALUE self)
|
52
|
-
{
|
53
|
-
VALUE input = rb_class_new_instance(0, NULL, cXMLInput);
|
54
|
-
rb_iv_set(self, "@input", input);
|
55
|
-
return self;
|
56
|
-
}
|
57
|
-
|
58
|
-
/* Parsing data sources */
|
59
|
-
static int rxml_sax_parser_parse_file(VALUE self, VALUE input)
|
60
|
-
{
|
61
|
-
VALUE handler = rb_ivar_get(self, CALLBACKS_ATTR);
|
62
|
-
VALUE file = rb_ivar_get(input, FILE_ATTR);
|
63
|
-
return xmlSAXUserParseFile((xmlSAXHandlerPtr) &rxml_sax_handler,
|
64
|
-
(void *) handler, StringValuePtr(file));
|
65
|
-
}
|
66
|
-
|
67
|
-
static int rxml_sax_parser_parse_string(VALUE self, VALUE input)
|
68
|
-
{
|
69
|
-
VALUE handler = rb_ivar_get(self, CALLBACKS_ATTR);
|
70
|
-
VALUE str = rb_ivar_get(input, STRING_ATTR);
|
71
|
-
return xmlSAXUserParseMemory((xmlSAXHandlerPtr) &rxml_sax_handler,
|
72
|
-
(void *) handler, StringValuePtr(str), RSTRING_LEN(str));
|
73
|
-
}
|
74
47
|
|
75
|
-
static int rxml_sax_parser_parse_io(VALUE self, VALUE input)
|
48
|
+
/*static int rxml_sax_parser_parse_io(VALUE self, VALUE input)
|
76
49
|
{
|
77
50
|
VALUE handler = rb_ivar_get(self, CALLBACKS_ATTR);
|
78
51
|
VALUE io = rb_ivar_get(input, IO_ATTR);
|
@@ -83,6 +56,30 @@ static int rxml_sax_parser_parse_io(VALUE self, VALUE input)
|
|
83
56
|
(void *) handler, (xmlInputReadCallback) rxml_read_callback, NULL,
|
84
57
|
(void *) io, xmlEncoding);
|
85
58
|
return xmlParseDocument(ctxt);
|
59
|
+
}*/
|
60
|
+
|
61
|
+
|
62
|
+
/*
|
63
|
+
* call-seq:
|
64
|
+
* parser.initialize(context) -> XML::Parser
|
65
|
+
*
|
66
|
+
* Creates a new XML::Parser from the specified
|
67
|
+
* XML::Parser::Context.
|
68
|
+
*/
|
69
|
+
static VALUE rxml_sax_parser_initialize(int argc, VALUE *argv, VALUE self)
|
70
|
+
{
|
71
|
+
VALUE context = Qnil;
|
72
|
+
|
73
|
+
rb_scan_args(argc, argv, "01", &context);
|
74
|
+
|
75
|
+
if (context == Qnil)
|
76
|
+
{
|
77
|
+
rb_warn("Passing no parameters to XML::SaxParser.new is deprecated. Pass an instance of XML::Parser::Context instead.");
|
78
|
+
context = rb_class_new_instance(0, NULL, cXMLParserContext);
|
79
|
+
}
|
80
|
+
|
81
|
+
rb_ivar_set(self, CONTEXT_ATTR, context);
|
82
|
+
return self;
|
86
83
|
}
|
87
84
|
|
88
85
|
/*
|
@@ -95,26 +92,33 @@ static int rxml_sax_parser_parse_io(VALUE self, VALUE input)
|
|
95
92
|
static VALUE rxml_sax_parser_parse(VALUE self)
|
96
93
|
{
|
97
94
|
int status;
|
98
|
-
VALUE
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
95
|
+
VALUE context = rb_ivar_get(self, CONTEXT_ATTR);
|
96
|
+
xmlParserCtxtPtr ctxt;
|
97
|
+
Data_Get_Struct(context, xmlParserCtxt, ctxt);
|
98
|
+
|
99
|
+
ctxt->sax2 = 1;
|
100
|
+
ctxt->userData = (void*)rb_ivar_get(self, CALLBACKS_ATTR);
|
101
|
+
|
102
|
+
if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
|
103
|
+
xmlFree(ctxt->sax);
|
104
|
+
|
105
|
+
ctxt->sax = (xmlSAXHandlerPtr)&rxml_sax_handler;
|
106
|
+
|
107
|
+
status = xmlParseDocument(ctxt);
|
108
|
+
|
109
|
+
/* IMPORTANT - null the handle to our sax handler
|
110
|
+
so libxml doesn't try to free it.*/
|
111
|
+
ctxt->sax = NULL;
|
112
|
+
|
113
|
+
/* Now check the parsing result*/
|
114
|
+
if (status == -1 || !ctxt->wellFormed)
|
110
115
|
{
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
{
|
116
|
-
return (Qtrue);
|
116
|
+
if (ctxt->myDoc)
|
117
|
+
xmlFreeDoc(ctxt->myDoc);
|
118
|
+
|
119
|
+
rxml_raise(&ctxt->lastError);
|
117
120
|
}
|
121
|
+
return Qtrue;
|
118
122
|
}
|
119
123
|
|
120
124
|
// Rdoc needs to know
|
@@ -130,11 +134,10 @@ void ruby_init_xml_sax_parser(void)
|
|
130
134
|
|
131
135
|
/* Atributes */
|
132
136
|
CALLBACKS_ATTR = rb_intern("@callbacks");
|
133
|
-
|
137
|
+
CONTEXT_ATTR = rb_intern("@context");
|
134
138
|
rb_define_attr(cXMLSaxParser, "callbacks", 1, 1);
|
135
|
-
rb_define_attr(cXMLSaxParser, "input", 1, 0);
|
136
139
|
|
137
140
|
/* Instance Methods */
|
138
|
-
rb_define_method(cXMLSaxParser, "initialize", rxml_sax_parser_initialize,
|
141
|
+
rb_define_method(cXMLSaxParser, "initialize", rxml_sax_parser_initialize, -1);
|
139
142
|
rb_define_method(cXMLSaxParser, "parse", rxml_sax_parser_parse, 0);
|
140
|
-
}
|
143
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: ruby_xml_xpath_context.c
|
1
|
+
/* $Id: ruby_xml_xpath_context.c 739 2009-01-23 03:42:09Z cfis $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
@@ -23,6 +23,8 @@
|
|
23
23
|
|
24
24
|
VALUE cXMLXPathContext;
|
25
25
|
|
26
|
+
static ID DOC_ATTRIBUTE;
|
27
|
+
|
26
28
|
static void rxml_xpath_context_free(xmlXPathContextPtr ctxt)
|
27
29
|
{
|
28
30
|
xmlXPathFreeContext(ctxt);
|
@@ -68,7 +70,7 @@ static VALUE rxml_xpath_context_initialize(VALUE self, VALUE node)
|
|
68
70
|
DATA_PTR(self) = xmlXPathNewContext(xdoc);
|
69
71
|
|
70
72
|
/* Save the doc as an attribute, this will expose it to Ruby's GC. */
|
71
|
-
|
73
|
+
rb_ivar_set(self, DOC_ATTRIBUTE, document);
|
72
74
|
|
73
75
|
return self;
|
74
76
|
}
|
@@ -245,9 +247,11 @@ static VALUE rxml_xpath_context_node_set(VALUE self, VALUE node)
|
|
245
247
|
|
246
248
|
/*
|
247
249
|
* call-seq:
|
248
|
-
* context.find("xpath") -> XML::XPath::Object
|
250
|
+
* context.find("xpath") -> true|false|number|string|XML::XPath::Object
|
249
251
|
*
|
250
|
-
*
|
252
|
+
* Executes the provided xpath function. The result depends on the execution
|
253
|
+
* of the xpath statement. It may be true, false, a number, a string or
|
254
|
+
* a node set.
|
251
255
|
*/
|
252
256
|
static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
|
253
257
|
{
|
@@ -283,12 +287,31 @@ static VALUE rxml_xpath_context_find(VALUE self, VALUE xpath_expr)
|
|
283
287
|
rxml_raise(xerror);
|
284
288
|
}
|
285
289
|
|
286
|
-
|
287
|
-
|
290
|
+
switch (xobject->type)
|
291
|
+
{
|
292
|
+
case XPATH_NODESET:
|
293
|
+
result = rxml_xpath_object_wrap(xctxt->doc, xobject);
|
294
|
+
break;
|
295
|
+
case XPATH_BOOLEAN:
|
296
|
+
result = (xobject->boolval != 0) ? Qtrue : Qfalse;
|
297
|
+
xmlXPathFreeObject(xobject);
|
298
|
+
break;
|
299
|
+
case XPATH_NUMBER:
|
300
|
+
result = rb_float_new(xobject->floatval);
|
301
|
+
xmlXPathFreeObject(xobject);
|
302
|
+
break;
|
303
|
+
case XPATH_STRING:
|
304
|
+
result = rb_str_new2((const char*)xobject->stringval);
|
305
|
+
xmlXPathFreeObject(xobject);
|
306
|
+
break;
|
307
|
+
default:
|
308
|
+
result = Qnil;
|
309
|
+
xmlXPathFreeObject(xobject);
|
310
|
+
}
|
288
311
|
return result;
|
289
312
|
}
|
290
313
|
|
291
|
-
|
314
|
+
#if LIBXML_VERSION >= 20626
|
292
315
|
/*
|
293
316
|
* call-seq:
|
294
317
|
* context.enable_cache(size = nil)
|
@@ -327,7 +350,8 @@ rxml_xpath_context_enable_cache(int argc, VALUE *argv, VALUE self)
|
|
327
350
|
* Disables an XPath::Context's built-in cache.
|
328
351
|
*/
|
329
352
|
static VALUE
|
330
|
-
rxml_xpath_context_disable_cache(VALUE self)
|
353
|
+
rxml_xpath_context_disable_cache(VALUE self)
|
354
|
+
{
|
331
355
|
xmlXPathContextPtr xctxt;
|
332
356
|
Data_Get_Struct(self, xmlXPathContext, xctxt);
|
333
357
|
|
@@ -336,10 +360,19 @@ rxml_xpath_context_disable_cache(VALUE self) {
|
|
336
360
|
|
337
361
|
return self;
|
338
362
|
}
|
363
|
+
#endif
|
364
|
+
|
339
365
|
|
366
|
+
// Rdoc needs to know
|
367
|
+
#ifdef RDOC_NEVER_DEFINED
|
368
|
+
mLibXML = rb_define_module("LibXML");
|
369
|
+
mXPath = rb_define_module_under(mLibXML, "XPath");
|
370
|
+
#endif
|
340
371
|
|
341
372
|
void ruby_init_xml_xpath_context(void)
|
342
373
|
{
|
374
|
+
DOC_ATTRIBUTE = rb_intern("@doc");
|
375
|
+
|
343
376
|
cXMLXPathContext = rb_define_class_under(mXPath, "Context", rb_cObject);
|
344
377
|
rb_define_alloc_func(cXMLXPathContext, rxml_xpath_context_alloc);
|
345
378
|
rb_define_attr(cXMLXPathContext, "doc", 1, 0);
|
@@ -349,6 +382,8 @@ void ruby_init_xml_xpath_context(void)
|
|
349
382
|
rb_define_method(cXMLXPathContext, "register_namespace", rxml_xpath_context_register_namespace, 2);
|
350
383
|
rb_define_method(cXMLXPathContext, "node=", rxml_xpath_context_node_set, 1);
|
351
384
|
rb_define_method(cXMLXPathContext, "find", rxml_xpath_context_find, 1);
|
385
|
+
#if LIBXML_VERSION >= 20626
|
352
386
|
rb_define_method(cXMLXPathContext, "enable_cache", rxml_xpath_context_enable_cache, -1);
|
353
387
|
rb_define_method(cXMLXPathContext, "disable_cache", rxml_xpath_context_disable_cache, 0);
|
388
|
+
#endif
|
354
389
|
}
|
@@ -58,6 +58,12 @@ static VALUE rxml_xpath_expression_initialize(VALUE self, VALUE expression)
|
|
58
58
|
return self;
|
59
59
|
}
|
60
60
|
|
61
|
+
// Rdoc needs to know
|
62
|
+
#ifdef RDOC_NEVER_DEFINED
|
63
|
+
mLibXML = rb_define_module("LibXML");
|
64
|
+
mXPath = rb_define_module_under(mLibXML, "XPath");
|
65
|
+
#endif
|
66
|
+
|
61
67
|
void ruby_init_xml_xpath_expression(void)
|
62
68
|
{
|
63
69
|
cXMLXPathExpression = rb_define_class_under(mXPath, "Expression", rb_cObject);
|
@@ -7,91 +7,90 @@
|
|
7
7
|
*
|
8
8
|
* A collection of nodes returned from the evaluation of an XML::XPath
|
9
9
|
* or XML::XPointer expression.
|
10
|
-
*
|
11
10
|
*/
|
12
|
-
VALUE cXMLXPathObject;
|
13
|
-
|
14
|
-
static xmlDocPtr rxml_xpath_object_doc(xmlXPathObjectPtr xpop)
|
15
|
-
{
|
16
|
-
xmlDocPtr result = NULL;
|
17
|
-
xmlNodePtr *nodes = NULL;
|
18
11
|
|
19
|
-
|
20
|
-
return result;
|
12
|
+
VALUE cXMLXPathObject;
|
21
13
|
|
22
|
-
if (!xpop->nodesetval || !xpop->nodesetval->nodeTab)
|
23
|
-
return result;
|
24
14
|
|
25
|
-
|
15
|
+
/* Memory management of xpath results is tricky. If a nodeset is
|
16
|
+
returned, it generally consists of pointers to nodes in the
|
17
|
+
original document. However, namespace nodes are handled differently -
|
18
|
+
libxml creates copies of them instead. Thus, when an xmlXPathObjectPtr
|
19
|
+
is freed, libxml iterates over the results to find the copied namespace
|
20
|
+
nodes to free them.
|
26
21
|
|
27
|
-
|
28
|
-
|
22
|
+
This causes problems for the bindings because the underlying document
|
23
|
+
may be freed before the xmlXPathObjectPtr instance. This might seem
|
24
|
+
counterintuitive since the xmlXPathObjectPtr marks the document.
|
25
|
+
However, once both objects go out of scope, the order of their
|
26
|
+
destruction is random.
|
29
27
|
|
30
|
-
|
31
|
-
|
28
|
+
To deal with this, the wrapper code searches for the namespace nodes
|
29
|
+
and wraps them in Ruby objects. When the Ruby objects go out of scope
|
30
|
+
then the namespace nodes are freed. */
|
32
31
|
|
33
|
-
static void
|
32
|
+
static void rxml_xpath_object_free(rxml_xpath_object *rxpop)
|
34
33
|
{
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
/* We positively, absolutely cannot let libxml iterate over
|
35
|
+
the nodeTab since if the underlying document has been
|
36
|
+
freed the majority of entries are invalid, resulting in
|
37
|
+
segmentation faults.*/
|
38
|
+
if (rxpop->xpop->nodesetval && rxpop->xpop->nodesetval->nodeTab)
|
38
39
|
{
|
39
|
-
|
40
|
-
|
41
|
-
rb_gc_mark((VALUE) xdoc->_private);
|
42
|
-
|
43
|
-
for (i = 0; i < xpop->nodesetval->nodeNr; i++)
|
44
|
-
{
|
45
|
-
if (xpop->nodesetval->nodeTab[i]->_private)
|
46
|
-
rb_gc_mark((VALUE) xpop->nodesetval->nodeTab[i]->_private);
|
47
|
-
}
|
40
|
+
xmlFree(rxpop->xpop->nodesetval->nodeTab);
|
41
|
+
rxpop->xpop->nodesetval->nodeTab = NULL;
|
48
42
|
}
|
43
|
+
xmlXPathFreeObject(rxpop->xpop);
|
44
|
+
xfree(rxpop);
|
49
45
|
}
|
50
46
|
|
51
|
-
|
47
|
+
/* Custom free function for copied namespace nodes */
|
48
|
+
static void rxml_namespace_xpath_free(xmlNsPtr xns)
|
52
49
|
{
|
53
|
-
|
54
|
-
|
55
|
-
xmlXPathFreeNodeSetList(xpop);
|
50
|
+
xns->_private = NULL;
|
51
|
+
xmlFreeNs(xns);
|
56
52
|
}
|
57
53
|
|
58
|
-
|
54
|
+
static void rxml_xpath_object_mark(rxml_xpath_object *rxpop)
|
59
55
|
{
|
60
|
-
|
56
|
+
rb_gc_mark(rxpop->nsnodes);
|
57
|
+
if (rxpop->xdoc->_private)
|
58
|
+
rb_gc_mark((VALUE)rxpop->xdoc->_private);
|
59
|
+
}
|
61
60
|
|
62
|
-
|
63
|
-
|
61
|
+
VALUE rxml_xpath_object_wrap(xmlDocPtr xdoc, xmlXPathObjectPtr xpop)
|
62
|
+
{
|
63
|
+
int i;
|
64
|
+
rxml_xpath_object *rxpop = ALLOC(rxml_xpath_object);
|
65
|
+
rxpop->xdoc =xdoc;
|
66
|
+
rxpop->xpop = xpop;
|
67
|
+
rxpop->nsnodes = rb_ary_new();
|
64
68
|
|
65
|
-
|
69
|
+
/* Find all the extra namespace nodes and wrap them. */
|
70
|
+
if (xpop->nodesetval && xpop->nodesetval->nodeNr)
|
66
71
|
{
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
rval = rb_str_new2((const char*)xpop->stringval);
|
87
|
-
|
88
|
-
xmlXPathFreeObject(xpop);
|
89
|
-
break;
|
90
|
-
default:
|
91
|
-
xmlXPathFreeObject(xpop);
|
92
|
-
rval = Qnil;
|
72
|
+
for (i = 0;i < xpop->nodesetval->nodeNr; i++)
|
73
|
+
{
|
74
|
+
xmlNodePtr xnode = xpop->nodesetval->nodeTab[i];
|
75
|
+
if (xnode!= NULL && xnode->type == XML_NAMESPACE_DECL)
|
76
|
+
{
|
77
|
+
VALUE ns = Qnil;
|
78
|
+
xmlNsPtr xns = (xmlNsPtr)xnode;
|
79
|
+
|
80
|
+
/* Get rid of libxml's -> next hack. The issue here is
|
81
|
+
the rxml_namespace code assumes that ns->next refers
|
82
|
+
to another namespace. */
|
83
|
+
xns->next = NULL;
|
84
|
+
|
85
|
+
/* Specify a custom free function here since by default
|
86
|
+
namespace nodes will not be freed */
|
87
|
+
ns = rxml_namespace_wrap((xmlNsPtr)xnode, (RUBY_DATA_FUNC)rxml_namespace_xpath_free);
|
88
|
+
rb_ary_push(rxpop->nsnodes, ns);
|
89
|
+
}
|
90
|
+
}
|
93
91
|
}
|
94
|
-
|
92
|
+
|
93
|
+
return Data_Wrap_Struct(cXMLXPathObject, rxml_xpath_object_mark, rxml_xpath_object_free, rxpop);
|
95
94
|
}
|
96
95
|
|
97
96
|
static VALUE rxml_xpath_object_tabref(xmlXPathObjectPtr xpop, int apos)
|
@@ -108,8 +107,11 @@ static VALUE rxml_xpath_object_tabref(xmlXPathObjectPtr xpop, int apos)
|
|
108
107
|
case XML_ATTRIBUTE_NODE:
|
109
108
|
return rxml_attr_wrap((xmlAttrPtr) xpop->nodesetval->nodeTab[apos]);
|
110
109
|
break;
|
110
|
+
case XML_NAMESPACE_DECL:
|
111
|
+
return rxml_namespace_wrap((xmlNsPtr)xpop->nodesetval->nodeTab[apos], NULL);
|
112
|
+
break;
|
111
113
|
default:
|
112
|
-
return rxml_node_wrap(
|
114
|
+
return rxml_node_wrap(xpop->nodesetval->nodeTab[apos]);
|
113
115
|
}
|
114
116
|
}
|
115
117
|
|
@@ -122,12 +124,15 @@ static VALUE rxml_xpath_object_tabref(xmlXPathObjectPtr xpop, int apos)
|
|
122
124
|
static VALUE rxml_xpath_object_to_a(VALUE self)
|
123
125
|
{
|
124
126
|
VALUE set_ary, nodeobj;
|
127
|
+
rxml_xpath_object *rxpop;
|
125
128
|
xmlXPathObjectPtr xpop;
|
126
129
|
int i;
|
127
130
|
|
128
|
-
Data_Get_Struct(self,
|
131
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
132
|
+
xpop = rxpop->xpop;
|
129
133
|
|
130
134
|
set_ary = rb_ary_new();
|
135
|
+
|
131
136
|
if (!((xpop->nodesetval == NULL) || (xpop->nodesetval->nodeNr == 0)))
|
132
137
|
{
|
133
138
|
for (i = 0; i < xpop->nodesetval->nodeNr; i++)
|
@@ -148,14 +153,13 @@ static VALUE rxml_xpath_object_to_a(VALUE self)
|
|
148
153
|
*/
|
149
154
|
static VALUE rxml_xpath_object_empty_q(VALUE self)
|
150
155
|
{
|
151
|
-
|
156
|
+
rxml_xpath_object *rxpop;
|
157
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
152
158
|
|
153
|
-
|
154
|
-
|
155
|
-
if (xpop->type != XPATH_NODESET)
|
159
|
+
if (rxpop->xpop->type != XPATH_NODESET)
|
156
160
|
return Qnil;
|
157
161
|
|
158
|
-
return (xpop->nodesetval == NULL || xpop->nodesetval->nodeNr <= 0) ? Qtrue
|
162
|
+
return (rxpop->xpop->nodesetval == NULL || rxpop->xpop->nodesetval->nodeNr <= 0) ? Qtrue
|
159
163
|
: Qfalse;
|
160
164
|
}
|
161
165
|
|
@@ -167,17 +171,17 @@ static VALUE rxml_xpath_object_empty_q(VALUE self)
|
|
167
171
|
*/
|
168
172
|
static VALUE rxml_xpath_object_each(VALUE self)
|
169
173
|
{
|
170
|
-
|
174
|
+
rxml_xpath_object *rxpop;
|
171
175
|
int i;
|
172
176
|
|
173
177
|
if (rxml_xpath_object_empty_q(self) == Qtrue)
|
174
178
|
return Qnil;
|
175
179
|
|
176
|
-
Data_Get_Struct(self,
|
180
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
177
181
|
|
178
|
-
for (i = 0; i < xpop->nodesetval->nodeNr; i++)
|
182
|
+
for (i = 0; i < rxpop->xpop->nodesetval->nodeNr; i++)
|
179
183
|
{
|
180
|
-
rb_yield(rxml_xpath_object_tabref(xpop, i));
|
184
|
+
rb_yield(rxml_xpath_object_tabref(rxpop->xpop, i));
|
181
185
|
}
|
182
186
|
return (self);
|
183
187
|
}
|
@@ -190,10 +194,13 @@ static VALUE rxml_xpath_object_each(VALUE self)
|
|
190
194
|
*/
|
191
195
|
static VALUE rxml_xpath_object_first(VALUE self)
|
192
196
|
{
|
197
|
+
rxml_xpath_object *rxpop;
|
198
|
+
|
193
199
|
if (rxml_xpath_object_empty_q(self) == Qtrue)
|
194
200
|
return Qnil;
|
195
201
|
|
196
|
-
|
202
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
203
|
+
return rxml_xpath_object_tabref(rxpop->xpop, 0);
|
197
204
|
}
|
198
205
|
|
199
206
|
/*
|
@@ -204,11 +211,13 @@ static VALUE rxml_xpath_object_first(VALUE self)
|
|
204
211
|
*/
|
205
212
|
static VALUE rxml_xpath_object_aref(VALUE self, VALUE aref)
|
206
213
|
{
|
214
|
+
rxml_xpath_object *rxpop;
|
215
|
+
|
207
216
|
if (rxml_xpath_object_empty_q(self) == Qtrue)
|
208
217
|
return Qnil;
|
209
218
|
|
210
|
-
|
211
|
-
|
219
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
220
|
+
return rxml_xpath_object_tabref(rxpop->xpop, NUM2INT(aref));
|
212
221
|
}
|
213
222
|
|
214
223
|
/*
|
@@ -219,14 +228,13 @@ static VALUE rxml_xpath_object_aref(VALUE self, VALUE aref)
|
|
219
228
|
*/
|
220
229
|
static VALUE rxml_xpath_object_length(VALUE self)
|
221
230
|
{
|
222
|
-
|
231
|
+
rxml_xpath_object *rxpop;
|
223
232
|
|
224
233
|
if (rxml_xpath_object_empty_q(self) == Qtrue)
|
225
234
|
return INT2FIX(0);
|
226
235
|
|
227
|
-
Data_Get_Struct(self,
|
228
|
-
|
229
|
-
return INT2NUM(xpop->nodesetval->nodeNr);
|
236
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
237
|
+
return INT2NUM(rxpop->xpop->nodesetval->nodeNr);
|
230
238
|
}
|
231
239
|
|
232
240
|
/*
|
@@ -250,11 +258,9 @@ static VALUE rxml_xpath_object_length(VALUE self)
|
|
250
258
|
*/
|
251
259
|
static VALUE rxml_xpath_object_get_type(VALUE self)
|
252
260
|
{
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
return INT2FIX(xpop->type);
|
261
|
+
rxml_xpath_object *rxpop;
|
262
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
263
|
+
return INT2FIX(rxpop->xpop->type);
|
258
264
|
}
|
259
265
|
|
260
266
|
/*
|
@@ -265,14 +271,14 @@ static VALUE rxml_xpath_object_get_type(VALUE self)
|
|
265
271
|
*/
|
266
272
|
static VALUE rxml_xpath_object_string(VALUE self)
|
267
273
|
{
|
268
|
-
|
274
|
+
rxml_xpath_object *rxpop;
|
269
275
|
|
270
|
-
Data_Get_Struct(self,
|
276
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
271
277
|
|
272
|
-
if (xpop->stringval == NULL)
|
278
|
+
if (rxpop->xpop->stringval == NULL)
|
273
279
|
return Qnil;
|
274
280
|
|
275
|
-
return rb_str_new2((const char*) xpop->stringval);
|
281
|
+
return rb_str_new2((const char*) rxpop->xpop->stringval);
|
276
282
|
}
|
277
283
|
|
278
284
|
/*
|
@@ -285,9 +291,9 @@ static VALUE rxml_xpath_object_string(VALUE self)
|
|
285
291
|
static VALUE rxml_xpath_object_debug(VALUE self)
|
286
292
|
{
|
287
293
|
#ifdef LIBXML_DEBUG_ENABLED
|
288
|
-
|
289
|
-
Data_Get_Struct(self,
|
290
|
-
xmlXPathDebugDumpObject(stdout, xpop, 0);
|
294
|
+
rxml_xpath_object *rxpop;
|
295
|
+
Data_Get_Struct(self, rxml_xpath_object, rxpop);
|
296
|
+
xmlXPathDebugDumpObject(stdout, rxpop->xpop, 0);
|
291
297
|
return Qtrue;
|
292
298
|
#else
|
293
299
|
rb_warn("libxml was compiled without debugging support.")
|
@@ -295,6 +301,12 @@ static VALUE rxml_xpath_object_debug(VALUE self)
|
|
295
301
|
#endif
|
296
302
|
}
|
297
303
|
|
304
|
+
// Rdoc needs to know
|
305
|
+
#ifdef RDOC_NEVER_DEFINED
|
306
|
+
mLibXML = rb_define_module("LibXML");
|
307
|
+
mXPath = rb_define_module_under(mLibXML, "XPath");
|
308
|
+
#endif
|
309
|
+
|
298
310
|
void ruby_init_xml_xpath_object(void)
|
299
311
|
{
|
300
312
|
cXMLXPathObject = rb_define_class_under(mXPath, "Object", rb_cObject);
|