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.
Files changed (97) 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/vc/libxml_ruby.vcproj +43 -3
  47. data/lib/libxml.rb +2 -3
  48. data/lib/libxml/attr.rb +71 -2
  49. data/lib/libxml/attr_decl.rb +81 -0
  50. data/lib/libxml/document.rb +78 -14
  51. data/lib/libxml/html_parser.rb +75 -42
  52. data/lib/libxml/node.rb +11 -0
  53. data/lib/libxml/parser.rb +106 -62
  54. data/lib/libxml/reader.rb +12 -0
  55. data/lib/libxml/sax_parser.rb +42 -52
  56. data/lib/libxml/xpath_object.rb +15 -0
  57. data/test/model/atom.xml +12 -12
  58. data/test/model/bands.xml +4 -4
  59. data/test/model/books.xml +146 -147
  60. data/test/model/merge_bug_data.xml +1 -1
  61. data/test/model/rubynet.xml +1 -0
  62. data/test/model/shiporder.rng +1 -1
  63. data/test/model/shiporder.xml +22 -22
  64. data/test/model/shiporder.xsd +30 -30
  65. data/test/model/xinclude.xml +1 -1
  66. data/test/{tc_node_attr.rb → tc_attr.rb} +1 -1
  67. data/test/tc_attr_decl.rb +131 -0
  68. data/test/tc_deprecated_require.rb +1 -3
  69. data/test/tc_document.rb +13 -3
  70. data/test/tc_document_write.rb +5 -5
  71. data/test/tc_dtd.rb +13 -5
  72. data/test/tc_html_parser.rb +14 -26
  73. data/test/tc_node_cdata.rb +1 -3
  74. data/test/tc_node_comment.rb +2 -4
  75. data/test/tc_node_edit.rb +2 -3
  76. data/test/tc_node_text.rb +35 -1
  77. data/test/tc_node_write.rb +3 -3
  78. data/test/tc_node_xlink.rb +2 -4
  79. data/test/tc_parser.rb +163 -70
  80. data/test/tc_parser_context.rb +103 -42
  81. data/test/tc_reader.rb +173 -45
  82. data/test/tc_relaxng.rb +2 -2
  83. data/test/tc_sax_parser.rb +48 -52
  84. data/test/tc_schema.rb +2 -2
  85. data/test/tc_xpath.rb +37 -6
  86. data/test/tc_xpath_context.rb +7 -1
  87. data/test/tc_xpath_expression.rb +1 -3
  88. data/test/tc_xpointer.rb +1 -3
  89. data/test/test_suite.rb +2 -3
  90. metadata +20 -13
  91. data/ext/libxml/ruby_xml_input.c +0 -329
  92. data/ext/libxml/ruby_xml_input.h +0 -20
  93. data/lib/libxml/parser_context.rb +0 -17
  94. data/lib/libxml/parser_options.rb +0 -25
  95. data/test/model/simple.xml +0 -7
  96. data/test/tc_input.rb +0 -13
  97. 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);