libxml-ruby 2.8.0 → 2.9.0

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY +15 -0
  3. data/README.rdoc +7 -7
  4. data/Rakefile +80 -78
  5. data/ext/libxml/extconf.h +4 -0
  6. data/ext/libxml/extconf.rb +57 -116
  7. data/ext/libxml/libxml.c +4 -0
  8. data/ext/libxml/ruby_xml.c +977 -893
  9. data/ext/libxml/ruby_xml.h +20 -10
  10. data/ext/libxml/ruby_xml_attr.c +333 -333
  11. data/ext/libxml/ruby_xml_attr_decl.c +2 -2
  12. data/ext/libxml/ruby_xml_cbg.c +85 -85
  13. data/ext/libxml/ruby_xml_document.c +1133 -1147
  14. data/ext/libxml/ruby_xml_dtd.c +261 -268
  15. data/ext/libxml/ruby_xml_encoding.c +262 -260
  16. data/ext/libxml/ruby_xml_encoding.h +19 -19
  17. data/ext/libxml/ruby_xml_html_parser_context.c +337 -338
  18. data/ext/libxml/ruby_xml_input_cbg.c +191 -191
  19. data/ext/libxml/ruby_xml_io.c +52 -50
  20. data/ext/libxml/ruby_xml_namespace.c +2 -2
  21. data/ext/libxml/ruby_xml_node.c +1446 -1452
  22. data/ext/libxml/ruby_xml_parser_context.c +999 -1001
  23. data/ext/libxml/ruby_xml_reader.c +1226 -1228
  24. data/ext/libxml/ruby_xml_relaxng.c +110 -111
  25. data/ext/libxml/ruby_xml_sax2_handler.c +326 -328
  26. data/ext/libxml/ruby_xml_schema.c +300 -301
  27. data/ext/libxml/ruby_xml_version.h +3 -3
  28. data/ext/libxml/ruby_xml_writer.c +14 -15
  29. data/ext/libxml/ruby_xml_xpath.c +188 -188
  30. data/ext/libxml/ruby_xml_xpath_context.c +360 -361
  31. data/ext/libxml/ruby_xml_xpath_object.c +335 -335
  32. data/libxml-ruby.gemspec +47 -44
  33. data/test/tc_attr.rb +5 -7
  34. data/test/tc_attr_decl.rb +5 -6
  35. data/test/tc_attributes.rb +1 -2
  36. data/test/tc_canonicalize.rb +1 -2
  37. data/test/tc_deprecated_require.rb +1 -2
  38. data/test/tc_document.rb +4 -5
  39. data/test/tc_document_write.rb +2 -3
  40. data/test/tc_dtd.rb +4 -5
  41. data/test/tc_encoding.rb +126 -126
  42. data/test/tc_encoding_sax.rb +4 -3
  43. data/test/tc_error.rb +14 -15
  44. data/test/tc_html_parser.rb +15 -7
  45. data/test/tc_html_parser_context.rb +1 -2
  46. data/test/tc_namespace.rb +2 -3
  47. data/test/tc_namespaces.rb +5 -6
  48. data/test/tc_node.rb +2 -3
  49. data/test/tc_node_cdata.rb +2 -3
  50. data/test/tc_node_comment.rb +1 -2
  51. data/test/tc_node_copy.rb +1 -2
  52. data/test/tc_node_edit.rb +5 -7
  53. data/test/tc_node_pi.rb +1 -2
  54. data/test/tc_node_text.rb +2 -3
  55. data/test/tc_node_write.rb +2 -3
  56. data/test/tc_node_xlink.rb +1 -2
  57. data/test/tc_parser.rb +18 -24
  58. data/test/tc_parser_context.rb +6 -7
  59. data/test/tc_properties.rb +1 -2
  60. data/test/tc_reader.rb +9 -10
  61. data/test/tc_relaxng.rb +4 -5
  62. data/test/tc_sax_parser.rb +9 -10
  63. data/test/tc_schema.rb +4 -5
  64. data/test/tc_traversal.rb +1 -2
  65. data/test/tc_writer.rb +1 -2
  66. data/test/tc_xinclude.rb +1 -2
  67. data/test/tc_xml.rb +1 -2
  68. data/test/tc_xpath.rb +8 -9
  69. data/test/tc_xpath_context.rb +3 -4
  70. data/test/tc_xpath_expression.rb +3 -4
  71. data/test/tc_xpointer.rb +1 -3
  72. data/test/test_helper.rb +3 -1
  73. data/test/test_suite.rb +0 -1
  74. metadata +47 -11
  75. data/test/etc_doc_to_s.rb +0 -21
  76. data/test/ets_doc_file.rb +0 -17
  77. data/test/ets_doc_to_s.rb +0 -23
  78. data/test/ets_gpx.rb +0 -28
  79. data/test/ets_node_gc.rb +0 -23
  80. data/test/ets_test.xml +0 -2
  81. data/test/ets_tsr.rb +0 -11
@@ -1,9 +1,9 @@
1
1
  /* Don't nuke this block! It is used for automatically updating the
2
2
  * versions below. VERSION = string formatting, VERNUM = numbered
3
3
  * version for inline testing: increment both or none at all.*/
4
- #define RUBY_LIBXML_VERSION "2.8.0"
5
- #define RUBY_LIBXML_VERNUM 280
4
+ #define RUBY_LIBXML_VERSION "2.9.0"
5
+ #define RUBY_LIBXML_VERNUM 290
6
6
  #define RUBY_LIBXML_VER_MAJ 2
7
- #define RUBY_LIBXML_VER_MIN 8
7
+ #define RUBY_LIBXML_VER_MIN 9
8
8
  #define RUBY_LIBXML_VER_MIC 0
9
9
  #define RUBY_LIBXML_VER_PATCH 0
@@ -257,7 +257,7 @@ static VALUE rxml_writer_flush(int argc, VALUE *argv, VALUE self)
257
257
  VALUE content;
258
258
 
259
259
  #ifdef HAVE_RUBY_ENCODING_H
260
- content = rb_external_str_new_with_enc(rwo->buffer->content, rwo->buffer->use, rwo->encoding);
260
+ content = rb_external_str_new_with_enc((const char*)rwo->buffer->content, rwo->buffer->use, rwo->encoding);
261
261
  #else
262
262
  content = rb_str_new(rwo->buffer->content, rwo->buffer->use);
263
263
  #endif /* HAVE_RUBY_ENCODING_H */
@@ -280,20 +280,20 @@ static VALUE rxml_writer_flush(int argc, VALUE *argv, VALUE self)
280
280
  */
281
281
  static VALUE rxml_writer_result(VALUE self)
282
282
  {
283
- VALUE ret;
284
- rxml_writer_object *rwo;
283
+ VALUE ret = Qnil;
284
+ rxml_writer_object *rwo = rxml_textwriter_get(self);
285
+ int bytesWritten = xmlTextWriterFlush(rwo->writer);
285
286
 
286
- ret = Qnil;
287
- rwo = rxml_textwriter_get(self);
288
- if (-1 == (ret = xmlTextWriterFlush(rwo->writer))) {
287
+ if (bytesWritten == -1) {
289
288
  rxml_raise(&xmlLastError);
290
289
  }
290
+
291
291
  switch (rwo->output_type) {
292
292
  case RXMLW_OUTPUT_DOC:
293
293
  ret = rwo->output;
294
294
  break;
295
295
  case RXMLW_OUTPUT_STRING:
296
- ret = rxml_writer_c_to_ruby_string(rwo->buffer->content, rwo->buffer->use);
296
+ ret = rxml_writer_c_to_ruby_string((const char*)rwo->buffer->content, rwo->buffer->use);
297
297
  break;
298
298
  case RXMLW_OUTPUT_IO:
299
299
  case RXMLW_OUTPUT_NONE:
@@ -334,7 +334,8 @@ static VALUE numeric_rxml_writer_void(VALUE obj, int (*fn)(xmlTextWriterPtr))
334
334
  static VALUE numeric_rxml_writer_va_strings(VALUE obj, VALUE pe, size_t strings_count, int (*fn)(ANYARGS), ...)
335
335
  {
336
336
  va_list ap;
337
- int argc, ret;
337
+ size_t argc;
338
+ int ret = -1;
338
339
  rxml_writer_object *rwo;
339
340
  const xmlChar *argv[XMLWRITER_MAX_STRING_ARGS];
340
341
  VALUE utf8[XMLWRITER_MAX_STRING_ARGS], orig[XMLWRITER_MAX_STRING_ARGS];
@@ -342,7 +343,6 @@ static VALUE numeric_rxml_writer_va_strings(VALUE obj, VALUE pe, size_t strings_
342
343
  if (strings_count > XMLWRITER_MAX_STRING_ARGS) {
343
344
  rb_bug("more arguments than expected");
344
345
  }
345
- ret = -1;
346
346
  va_start(ap, fn);
347
347
  rwo = rxml_textwriter_get(obj);
348
348
  for (argc = 0; argc < strings_count; argc++) {
@@ -765,12 +765,11 @@ static VALUE rxml_writer_end_cdata(VALUE self)
765
765
  static VALUE rxml_writer_start_document(int argc, VALUE *argv, VALUE self)
766
766
  {
767
767
  int ret;
768
- VALUE options;
768
+ VALUE options = Qnil;
769
769
  rxml_writer_object *rwo;
770
- const char *xencoding, *xstandalone;
770
+ const xmlChar *xencoding = NULL;
771
+ const char *xstandalone = NULL;
771
772
 
772
- options = Qnil;
773
- xstandalone = xencoding = NULL;
774
773
  rb_scan_args(argc, argv, "01", &options);
775
774
  if (!NIL_P(options)) {
776
775
  VALUE encoding, standalone;
@@ -778,7 +777,7 @@ static VALUE rxml_writer_start_document(int argc, VALUE *argv, VALUE self)
778
777
  encoding = standalone = Qnil;
779
778
  Check_Type(options, T_HASH);
780
779
  encoding = rb_hash_aref(options, sEncoding);
781
- xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
780
+ xencoding = NIL_P(encoding) ? NULL : (const xmlChar*)xmlGetCharEncodingName(NUM2INT(encoding));
782
781
  standalone = rb_hash_aref(options, sStandalone);
783
782
  if (NIL_P(standalone)) {
784
783
  xstandalone = NULL;
@@ -790,7 +789,7 @@ static VALUE rxml_writer_start_document(int argc, VALUE *argv, VALUE self)
790
789
  #ifdef HAVE_RUBY_ENCODING_H
791
790
  rwo->encoding = rxml_figure_encoding(xencoding);
792
791
  #endif /* !HAVE_RUBY_ENCODING_H */
793
- ret = xmlTextWriterStartDocument(rwo->writer, NULL, xencoding, xstandalone);
792
+ ret = xmlTextWriterStartDocument(rwo->writer, NULL, (const char*)xencoding, xstandalone);
794
793
 
795
794
  return (-1 == ret ? Qfalse : Qtrue);
796
795
  }
@@ -1,188 +1,188 @@
1
- /*
2
- * Document-class: LibXML::XML::XPath
3
- *
4
- * The XML::XPath module is used to query XML documents. It is
5
- * usually accessed via the XML::Document#find or
6
- * XML::Node#find methods. For example:
7
- *
8
- * document.find('/foo', namespaces) -> XML::XPath::Object
9
- *
10
- * The optional namespaces parameter can be a string, array or
11
- * hash table.
12
- *
13
- * document.find('/foo', 'xlink:http://www.w3.org/1999/xlink')
14
- * document.find('/foo', ['xlink:http://www.w3.org/1999/xlink',
15
- * 'xi:http://www.w3.org/2001/XInclude')
16
- * document.find('/foo', 'xlink' => 'http://www.w3.org/1999/xlink',
17
- * 'xi' => 'http://www.w3.org/2001/XInclude')
18
- *
19
- *
20
- * === Working With Default Namespaces
21
- *
22
- * Finding namespaced elements and attributes can be tricky.
23
- * Lets work through an example of a document with a default
24
- * namespace:
25
- *
26
- * <?xml version="1.0" encoding="utf-8"?>
27
- * <feed xmlns="http://www.w3.org/2005/Atom">
28
- * <title type="text">Phil Bogle's Contacts</title>
29
- * </feed>
30
- *
31
- * To find nodes you must define the atom namespace for
32
- * libxml. One way to do this is:
33
- *
34
- * node = doc.find('atom:title', 'atom:http://www.w3.org/2005/Atom')
35
- *
36
- * Alternatively, you can register the default namespace like this:
37
- *
38
- * doc.root.namespaces.default_prefix = 'atom'
39
- * node = doc.find('atom:title')
40
- *
41
- * === More Complex Namespace Examples
42
- *
43
- * Lets work through some more complex examples using the
44
- * following xml document:
45
- *
46
- * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
47
- * <soap:Body>
48
- * <getManufacturerNamesResponse xmlns="http://services.somewhere.com">
49
- * <IDAndNameList xmlns="http://services.somewhere.com">
50
- * <ns1:IdAndName xmlns:ns1="http://domain.somewhere.com"/>
51
- * </IDAndNameList>
52
- * </getManufacturerNamesResponse>
53
- * </soap:Body>
54
- * </soap:Envelope>
55
- *
56
- * # Since the soap namespace is defined on the root
57
- * # node we can directly use it.
58
- * doc.find('/soap:Envelope')
59
- *
60
- * # Since the ns1 namespace is not defined on the root node
61
- * # we have to first register it with the xpath engine.
62
- * doc.find('//ns1:IdAndName',
63
- * 'ns1:http://domain.somewhere.com')
64
- *
65
- * # Since the getManufacturerNamesResponse element uses a default
66
- * # namespace we first have to give it a prefix and register
67
- * # it with the xpath engine.
68
- * doc.find('//ns:getManufacturerNamesResponse',
69
- * 'ns:http://services.somewhere.com')
70
- *
71
- * # Here is an example showing a complex namespace aware
72
- * # xpath expression.
73
- * doc.find('/soap:Envelope/soap:Body/ns0:getManufacturerNamesResponse/ns0:IDAndNameList/ns1:IdAndName',
74
- * ['ns0:http://services.somewhere.com', 'ns1:http://domain.somewhere.com'])
75
- */
76
-
77
-
78
- #include "ruby_libxml.h"
79
-
80
- VALUE mXPath;
81
-
82
- VALUE
83
- rxml_xpath_to_value(xmlXPathContextPtr xctxt, xmlXPathObjectPtr xobject) {
84
- VALUE result;
85
- int type;
86
-
87
- if (xobject == NULL) {
88
- /* xmlLastError is different than xctxt->lastError. Use
89
- xmlLastError since it has the message set while xctxt->lastError
90
- does not. */
91
- xmlErrorPtr xerror = xmlGetLastError();
92
- rxml_raise(xerror);
93
- }
94
-
95
- switch (type = xobject->type) {
96
- case XPATH_NODESET:
97
- result = rxml_xpath_object_wrap(xctxt->doc, xobject);
98
- break;
99
- case XPATH_BOOLEAN:
100
- result = (xobject->boolval != 0) ? Qtrue : Qfalse;
101
- xmlXPathFreeObject(xobject);
102
- break;
103
- case XPATH_NUMBER:
104
- result = rb_float_new(xobject->floatval);
105
- xmlXPathFreeObject(xobject);
106
- break;
107
- case XPATH_STRING:
108
- result = rxml_new_cstr((const char*)xobject->stringval, xctxt->doc->encoding);
109
- xmlXPathFreeObject(xobject);
110
- break;
111
- default:
112
- xmlXPathFreeObject(xobject);
113
- rb_raise(rb_eTypeError,
114
- "can't convert XPath object of type %d to Ruby value", type
115
- );
116
- }
117
-
118
- return result;
119
- }
120
-
121
- xmlXPathObjectPtr
122
- rxml_xpath_from_value(VALUE value) {
123
- xmlXPathObjectPtr result = NULL;
124
-
125
- switch (TYPE(value)) {
126
- case T_TRUE:
127
- case T_FALSE:
128
- result = xmlXPathNewBoolean(RTEST(value));
129
- break;
130
- case T_FIXNUM:
131
- case T_FLOAT:
132
- result = xmlXPathNewFloat(NUM2DBL(value));
133
- break;
134
- case T_STRING:
135
- result = xmlXPathWrapString(xmlStrdup((const xmlChar *)StringValuePtr(value)));
136
- break;
137
- case T_NIL:
138
- result = xmlXPathNewNodeSet(NULL);
139
- break;
140
- case T_ARRAY: {
141
- int i, j;
142
- result = xmlXPathNewNodeSet(NULL);
143
-
144
- for (i = RARRAY_LEN(value); i > 0; i--) {
145
- xmlXPathObjectPtr obj = rxml_xpath_from_value(rb_ary_shift(value));
146
-
147
- if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
148
- for (j = 0; j < obj->nodesetval->nodeNr; j++) {
149
- xmlXPathNodeSetAdd(result->nodesetval, obj->nodesetval->nodeTab[j]);
150
- }
151
- }
152
- }
153
- break;
154
- }
155
- default:
156
- rb_raise(rb_eTypeError,
157
- "can't convert object of type %s to XPath object", rb_obj_classname(value)
158
- );
159
- }
160
-
161
- return result;
162
- }
163
-
164
- void rxml_init_xpath(void)
165
- {
166
- mXPath = rb_define_module_under(mXML, "XPath");
167
-
168
- /* 0: Undefined value. */
169
- rb_define_const(mXPath, "UNDEFINED", INT2NUM(XPATH_UNDEFINED));
170
- /* 1: A nodeset, will be wrapped by XPath Object. */
171
- rb_define_const(mXPath, "NODESET", INT2NUM(XPATH_NODESET));
172
- /* 2: A boolean value. */
173
- rb_define_const(mXPath, "BOOLEAN", INT2NUM(XPATH_BOOLEAN));
174
- /* 3: A numeric value. */
175
- rb_define_const(mXPath, "NUMBER", INT2NUM(XPATH_NUMBER));
176
- /* 4: A string value. */
177
- rb_define_const(mXPath, "STRING", INT2NUM(XPATH_STRING));
178
- /* 5: An xpointer point */
179
- rb_define_const(mXPath, "POINT", INT2NUM(XPATH_POINT));
180
- /* 6: An xpointer range */
181
- rb_define_const(mXPath, "RANGE", INT2NUM(XPATH_RANGE));
182
- /* 7: An xpointer location set */
183
- rb_define_const(mXPath, "LOCATIONSET", INT2NUM(XPATH_LOCATIONSET));
184
- /* 8: XPath user type */
185
- rb_define_const(mXPath, "USERS", INT2NUM(XPATH_USERS));
186
- /* 9: An XSLT value tree, non modifiable */
187
- rb_define_const(mXPath, "XSLT_TREE", INT2NUM(XPATH_XSLT_TREE));
188
- }
1
+ /*
2
+ * Document-class: LibXML::XML::XPath
3
+ *
4
+ * The XML::XPath module is used to query XML documents. It is
5
+ * usually accessed via the XML::Document#find or
6
+ * XML::Node#find methods. For example:
7
+ *
8
+ * document.find('/foo', namespaces) -> XML::XPath::Object
9
+ *
10
+ * The optional namespaces parameter can be a string, array or
11
+ * hash table.
12
+ *
13
+ * document.find('/foo', 'xlink:http://www.w3.org/1999/xlink')
14
+ * document.find('/foo', ['xlink:http://www.w3.org/1999/xlink',
15
+ * 'xi:http://www.w3.org/2001/XInclude')
16
+ * document.find('/foo', 'xlink' => 'http://www.w3.org/1999/xlink',
17
+ * 'xi' => 'http://www.w3.org/2001/XInclude')
18
+ *
19
+ *
20
+ * === Working With Default Namespaces
21
+ *
22
+ * Finding namespaced elements and attributes can be tricky.
23
+ * Lets work through an example of a document with a default
24
+ * namespace:
25
+ *
26
+ * <?xml version="1.0" encoding="utf-8"?>
27
+ * <feed xmlns="http://www.w3.org/2005/Atom">
28
+ * <title type="text">Phil Bogle's Contacts</title>
29
+ * </feed>
30
+ *
31
+ * To find nodes you must define the atom namespace for
32
+ * libxml. One way to do this is:
33
+ *
34
+ * node = doc.find('atom:title', 'atom:http://www.w3.org/2005/Atom')
35
+ *
36
+ * Alternatively, you can register the default namespace like this:
37
+ *
38
+ * doc.root.namespaces.default_prefix = 'atom'
39
+ * node = doc.find('atom:title')
40
+ *
41
+ * === More Complex Namespace Examples
42
+ *
43
+ * Lets work through some more complex examples using the
44
+ * following xml document:
45
+ *
46
+ * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
47
+ * <soap:Body>
48
+ * <getManufacturerNamesResponse xmlns="http://services.somewhere.com">
49
+ * <IDAndNameList xmlns="http://services.somewhere.com">
50
+ * <ns1:IdAndName xmlns:ns1="http://domain.somewhere.com"/>
51
+ * </IDAndNameList>
52
+ * </getManufacturerNamesResponse>
53
+ * </soap:Body>
54
+ * </soap:Envelope>
55
+ *
56
+ * # Since the soap namespace is defined on the root
57
+ * # node we can directly use it.
58
+ * doc.find('/soap:Envelope')
59
+ *
60
+ * # Since the ns1 namespace is not defined on the root node
61
+ * # we have to first register it with the xpath engine.
62
+ * doc.find('//ns1:IdAndName',
63
+ * 'ns1:http://domain.somewhere.com')
64
+ *
65
+ * # Since the getManufacturerNamesResponse element uses a default
66
+ * # namespace we first have to give it a prefix and register
67
+ * # it with the xpath engine.
68
+ * doc.find('//ns:getManufacturerNamesResponse',
69
+ * 'ns:http://services.somewhere.com')
70
+ *
71
+ * # Here is an example showing a complex namespace aware
72
+ * # xpath expression.
73
+ * doc.find('/soap:Envelope/soap:Body/ns0:getManufacturerNamesResponse/ns0:IDAndNameList/ns1:IdAndName',
74
+ * ['ns0:http://services.somewhere.com', 'ns1:http://domain.somewhere.com'])
75
+ */
76
+
77
+
78
+ #include "ruby_libxml.h"
79
+
80
+ VALUE mXPath;
81
+
82
+ VALUE
83
+ rxml_xpath_to_value(xmlXPathContextPtr xctxt, xmlXPathObjectPtr xobject) {
84
+ VALUE result;
85
+ int type;
86
+
87
+ if (xobject == NULL) {
88
+ /* xmlLastError is different than xctxt->lastError. Use
89
+ xmlLastError since it has the message set while xctxt->lastError
90
+ does not. */
91
+ xmlErrorPtr xerror = xmlGetLastError();
92
+ rxml_raise(xerror);
93
+ }
94
+
95
+ switch (type = xobject->type) {
96
+ case XPATH_NODESET:
97
+ result = rxml_xpath_object_wrap(xctxt->doc, xobject);
98
+ break;
99
+ case XPATH_BOOLEAN:
100
+ result = (xobject->boolval != 0) ? Qtrue : Qfalse;
101
+ xmlXPathFreeObject(xobject);
102
+ break;
103
+ case XPATH_NUMBER:
104
+ result = rb_float_new(xobject->floatval);
105
+ xmlXPathFreeObject(xobject);
106
+ break;
107
+ case XPATH_STRING:
108
+ result = rxml_new_cstr(xobject->stringval, xctxt->doc->encoding);
109
+ xmlXPathFreeObject(xobject);
110
+ break;
111
+ default:
112
+ xmlXPathFreeObject(xobject);
113
+ rb_raise(rb_eTypeError,
114
+ "can't convert XPath object of type %d to Ruby value", type
115
+ );
116
+ }
117
+
118
+ return result;
119
+ }
120
+
121
+ xmlXPathObjectPtr
122
+ rxml_xpath_from_value(VALUE value) {
123
+ xmlXPathObjectPtr result = NULL;
124
+
125
+ switch (TYPE(value)) {
126
+ case T_TRUE:
127
+ case T_FALSE:
128
+ result = xmlXPathNewBoolean(RTEST(value));
129
+ break;
130
+ case T_FIXNUM:
131
+ case T_FLOAT:
132
+ result = xmlXPathNewFloat(NUM2DBL(value));
133
+ break;
134
+ case T_STRING:
135
+ result = xmlXPathWrapString(xmlStrdup((const xmlChar *)StringValuePtr(value)));
136
+ break;
137
+ case T_NIL:
138
+ result = xmlXPathNewNodeSet(NULL);
139
+ break;
140
+ case T_ARRAY: {
141
+ long i, j;
142
+ result = xmlXPathNewNodeSet(NULL);
143
+
144
+ for (i = RARRAY_LEN(value); i > 0; i--) {
145
+ xmlXPathObjectPtr obj = rxml_xpath_from_value(rb_ary_shift(value));
146
+
147
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
148
+ for (j = 0; j < obj->nodesetval->nodeNr; j++) {
149
+ xmlXPathNodeSetAdd(result->nodesetval, obj->nodesetval->nodeTab[j]);
150
+ }
151
+ }
152
+ }
153
+ break;
154
+ }
155
+ default:
156
+ rb_raise(rb_eTypeError,
157
+ "can't convert object of type %s to XPath object", rb_obj_classname(value)
158
+ );
159
+ }
160
+
161
+ return result;
162
+ }
163
+
164
+ void rxml_init_xpath(void)
165
+ {
166
+ mXPath = rb_define_module_under(mXML, "XPath");
167
+
168
+ /* 0: Undefined value. */
169
+ rb_define_const(mXPath, "UNDEFINED", INT2NUM(XPATH_UNDEFINED));
170
+ /* 1: A nodeset, will be wrapped by XPath Object. */
171
+ rb_define_const(mXPath, "NODESET", INT2NUM(XPATH_NODESET));
172
+ /* 2: A boolean value. */
173
+ rb_define_const(mXPath, "BOOLEAN", INT2NUM(XPATH_BOOLEAN));
174
+ /* 3: A numeric value. */
175
+ rb_define_const(mXPath, "NUMBER", INT2NUM(XPATH_NUMBER));
176
+ /* 4: A string value. */
177
+ rb_define_const(mXPath, "STRING", INT2NUM(XPATH_STRING));
178
+ /* 5: An xpointer point */
179
+ rb_define_const(mXPath, "POINT", INT2NUM(XPATH_POINT));
180
+ /* 6: An xpointer range */
181
+ rb_define_const(mXPath, "RANGE", INT2NUM(XPATH_RANGE));
182
+ /* 7: An xpointer location set */
183
+ rb_define_const(mXPath, "LOCATIONSET", INT2NUM(XPATH_LOCATIONSET));
184
+ /* 8: XPath user type */
185
+ rb_define_const(mXPath, "USERS", INT2NUM(XPATH_USERS));
186
+ /* 9: An XSLT value tree, non modifiable */
187
+ rb_define_const(mXPath, "XSLT_TREE", INT2NUM(XPATH_XSLT_TREE));
188
+ }