libxml-ruby 0.9.7-x86-mswin32-60 → 0.9.8-x86-mswin32-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. data/CHANGES +53 -0
  2. data/Rakefile +1 -0
  3. data/ext/libxml/build.log +4 -0
  4. data/ext/libxml/cbg.c +86 -86
  5. data/ext/libxml/libxml.c +878 -876
  6. data/ext/libxml/ruby_libxml.h +8 -4
  7. data/ext/libxml/ruby_xml_attr.c +36 -168
  8. data/ext/libxml/ruby_xml_attr.h +2 -4
  9. data/ext/libxml/ruby_xml_attr_decl.c +177 -0
  10. data/ext/libxml/ruby_xml_attr_decl.h +13 -0
  11. data/ext/libxml/ruby_xml_attributes.c +29 -20
  12. data/ext/libxml/ruby_xml_document.c +895 -898
  13. data/ext/libxml/ruby_xml_dtd.c +18 -1
  14. data/ext/libxml/ruby_xml_dtd.h +1 -0
  15. data/ext/libxml/ruby_xml_encoding.c +116 -0
  16. data/ext/libxml/ruby_xml_encoding.h +12 -0
  17. data/ext/libxml/ruby_xml_error.c +8 -2
  18. data/ext/libxml/ruby_xml_html_parser.c +53 -74
  19. data/ext/libxml/ruby_xml_html_parser.h +2 -3
  20. data/ext/libxml/ruby_xml_html_parser_context.c +145 -0
  21. data/ext/libxml/ruby_xml_html_parser_context.h +12 -0
  22. data/ext/libxml/ruby_xml_html_parser_options.c +48 -0
  23. data/ext/libxml/ruby_xml_html_parser_options.h +12 -0
  24. data/ext/libxml/ruby_xml_input_cbg.c +1 -1
  25. data/ext/libxml/ruby_xml_io.c +30 -0
  26. data/ext/libxml/ruby_xml_io.h +9 -0
  27. data/ext/libxml/ruby_xml_namespace.c +34 -16
  28. data/ext/libxml/ruby_xml_namespace.h +2 -2
  29. data/ext/libxml/ruby_xml_namespaces.c +6 -6
  30. data/ext/libxml/ruby_xml_node.c +1367 -1324
  31. data/ext/libxml/ruby_xml_node.h +2 -2
  32. data/ext/libxml/ruby_xml_parser.c +26 -78
  33. data/ext/libxml/ruby_xml_parser.h +1 -1
  34. data/ext/libxml/ruby_xml_parser_context.c +284 -13
  35. data/ext/libxml/ruby_xml_parser_context.h +1 -2
  36. data/ext/libxml/ruby_xml_parser_options.c +75 -0
  37. data/ext/libxml/ruby_xml_parser_options.h +14 -0
  38. data/ext/libxml/ruby_xml_reader.c +277 -183
  39. data/ext/libxml/ruby_xml_sax_parser.c +60 -57
  40. data/ext/libxml/ruby_xml_xpath_context.c +43 -8
  41. data/ext/libxml/ruby_xml_xpath_expression.c +6 -0
  42. data/ext/libxml/ruby_xml_xpath_object.c +107 -95
  43. data/ext/libxml/ruby_xml_xpath_object.h +9 -1
  44. data/ext/libxml/ruby_xml_xpointer.c +107 -107
  45. data/ext/libxml/version.h +2 -2
  46. data/ext/mingw/libxml_ruby.dll.a +0 -0
  47. data/ext/mingw/libxml_ruby.so +0 -0
  48. data/ext/vc/libxml_ruby.vcproj +43 -3
  49. data/lib/libxml.rb +2 -3
  50. data/lib/libxml/attr.rb +71 -2
  51. data/lib/libxml/attr_decl.rb +81 -0
  52. data/lib/libxml/document.rb +78 -14
  53. data/lib/libxml/html_parser.rb +75 -42
  54. data/lib/libxml/node.rb +11 -0
  55. data/lib/libxml/parser.rb +106 -62
  56. data/lib/libxml/reader.rb +12 -0
  57. data/lib/libxml/sax_parser.rb +42 -52
  58. data/lib/libxml/xpath_object.rb +15 -0
  59. data/test/model/atom.xml +12 -12
  60. data/test/model/bands.xml +4 -4
  61. data/test/model/books.xml +146 -147
  62. data/test/model/merge_bug_data.xml +1 -1
  63. data/test/model/rubynet.xml +1 -0
  64. data/test/model/shiporder.rng +1 -1
  65. data/test/model/shiporder.xml +22 -22
  66. data/test/model/shiporder.xsd +30 -30
  67. data/test/model/xinclude.xml +1 -1
  68. data/test/{tc_node_attr.rb → tc_attr.rb} +1 -1
  69. data/test/tc_attr_decl.rb +131 -0
  70. data/test/tc_deprecated_require.rb +1 -3
  71. data/test/tc_document.rb +13 -3
  72. data/test/tc_document_write.rb +5 -5
  73. data/test/tc_dtd.rb +13 -5
  74. data/test/tc_html_parser.rb +14 -26
  75. data/test/tc_node_cdata.rb +1 -3
  76. data/test/tc_node_comment.rb +2 -4
  77. data/test/tc_node_edit.rb +2 -3
  78. data/test/tc_node_text.rb +35 -1
  79. data/test/tc_node_write.rb +3 -3
  80. data/test/tc_node_xlink.rb +2 -4
  81. data/test/tc_parser.rb +163 -70
  82. data/test/tc_parser_context.rb +103 -42
  83. data/test/tc_reader.rb +173 -45
  84. data/test/tc_relaxng.rb +2 -2
  85. data/test/tc_sax_parser.rb +48 -52
  86. data/test/tc_schema.rb +2 -2
  87. data/test/tc_xpath.rb +37 -6
  88. data/test/tc_xpath_context.rb +7 -1
  89. data/test/tc_xpath_expression.rb +1 -3
  90. data/test/tc_xpointer.rb +1 -3
  91. data/test/test_suite.rb +2 -3
  92. metadata +20 -13
  93. data/ext/libxml/ruby_xml_input.c +0 -329
  94. data/ext/libxml/ruby_xml_input.h +0 -20
  95. data/lib/libxml/parser_context.rb +0 -17
  96. data/lib/libxml/parser_options.rb +0 -25
  97. data/test/model/simple.xml +0 -7
  98. data/test/tc_input.rb +0 -13
  99. data/test/tc_well_formed.rb +0 -11
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_sax_parser.c 684 2008-12-13 00:34:28Z cfis $ */
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
- * Note that the XML::SaxParser API is fairly complex, not well standardized,
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.new
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 input = rb_ivar_get(self, INPUT_ATTR);
99
-
100
- if (rb_ivar_get(input, FILE_ATTR) != Qnil)
101
- status = rxml_sax_parser_parse_file(self, input);
102
- else if (rb_ivar_get(input, STRING_ATTR) != Qnil)
103
- status = rxml_sax_parser_parse_string(self, input);
104
- else if (rb_ivar_get(input, IO_ATTR) != Qnil)
105
- status = rxml_sax_parser_parse_io(self, input);
106
- else
107
- rb_raise(rb_eArgError, "You must specify a parser data source");
108
-
109
- if (status)
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
- rxml_raise(&xmlLastError);
112
- return Qfalse;
113
- }
114
- else
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
- INPUT_ATTR = rb_intern("@input");
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, 0);
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 673 2008-12-08 06:33:23Z cfis $ */
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
- rb_iv_set(self, "@doc", document);
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
- * Find nodes matching the specified XPath expression
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
- result = rxml_xpath_object_wrap(xobject);
287
- rb_iv_set(result, "@context", self);
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
- if (xpop->type != XPATH_NODESET)
20
- return result;
12
+ VALUE cXMLXPathObject;
21
13
 
22
- if (!xpop->nodesetval || !xpop->nodesetval->nodeTab)
23
- return result;
24
14
 
25
- nodes = xpop->nodesetval->nodeTab;
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
- if (!(*nodes))
28
- return result;
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
- return (*nodes)->doc;
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 rxml_xpath_object_mark(xmlXPathObjectPtr xpop)
32
+ static void rxml_xpath_object_free(rxml_xpath_object *rxpop)
34
33
  {
35
- int i;
36
-
37
- if (xpop->type == XPATH_NODESET && xpop->nodesetval != NULL)
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
- xmlDocPtr xdoc = rxml_xpath_object_doc(xpop);
40
- if (xdoc && xdoc->_private)
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
- static void rxml_xpath_object_free(xmlXPathObjectPtr xpop)
47
+ /* Custom free function for copied namespace nodes */
48
+ static void rxml_namespace_xpath_free(xmlNsPtr xns)
52
49
  {
53
- /* Now free the xpath result but not underlying nodes
54
- since those belong to the document. */
55
- xmlXPathFreeNodeSetList(xpop);
50
+ xns->_private = NULL;
51
+ xmlFreeNs(xns);
56
52
  }
57
53
 
58
- VALUE rxml_xpath_object_wrap(xmlXPathObjectPtr xpop)
54
+ static void rxml_xpath_object_mark(rxml_xpath_object *rxpop)
59
55
  {
60
- VALUE rval;
56
+ rb_gc_mark(rxpop->nsnodes);
57
+ if (rxpop->xdoc->_private)
58
+ rb_gc_mark((VALUE)rxpop->xdoc->_private);
59
+ }
61
60
 
62
- if (xpop == NULL)
63
- return Qnil;
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
- switch (xpop->type)
69
+ /* Find all the extra namespace nodes and wrap them. */
70
+ if (xpop->nodesetval && xpop->nodesetval->nodeNr)
66
71
  {
67
- case XPATH_NODESET:
68
- rval = Data_Wrap_Struct(cXMLXPathObject, rxml_xpath_object_mark,
69
- rxml_xpath_object_free, xpop);
70
-
71
- break;
72
- case XPATH_BOOLEAN:
73
- if (xpop->boolval != 0)
74
- rval = Qtrue;
75
- else
76
- rval = Qfalse;
77
-
78
- xmlXPathFreeObject(xpop);
79
- break;
80
- case XPATH_NUMBER:
81
- rval = rb_float_new(xpop->floatval);
82
-
83
- xmlXPathFreeObject(xpop);
84
- break;
85
- case XPATH_STRING:
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
- return rval;
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(cXMLNode, xpop->nodesetval->nodeTab[apos]);
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, xmlXPathObject, xpop);
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
- xmlXPathObjectPtr xpop;
156
+ rxml_xpath_object *rxpop;
157
+ Data_Get_Struct(self, rxml_xpath_object, rxpop);
152
158
 
153
- Data_Get_Struct(self, xmlXPathObject, xpop);
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
- xmlXPathObjectPtr xpop;
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, xmlXPathObject, xpop);
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
- return rxml_xpath_object_tabref((xmlXPathObjectPtr) DATA_PTR(self), 0);
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
- return rxml_xpath_object_tabref((xmlXPathObjectPtr) DATA_PTR(self), NUM2INT(
211
- aref));
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
- xmlXPathObjectPtr xpop;
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, xmlXPathObject, xpop);
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
- xmlXPathObjectPtr xpop;
254
-
255
- Data_Get_Struct(self, xmlXPathObject, xpop);
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
- xmlXPathObjectPtr xpop;
274
+ rxml_xpath_object *rxpop;
269
275
 
270
- Data_Get_Struct(self, xmlXPathObject, xpop);
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
- xmlXPathObjectPtr xpop;
289
- Data_Get_Struct(self, xmlXPathObject, xpop);
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);