libxml-ruby 0.3.6

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 (74) hide show
  1. data/CHANGELOG +49 -0
  2. data/LICENSE +22 -0
  3. data/README +129 -0
  4. data/Rakefile +197 -0
  5. data/TODO +84 -0
  6. data/ext/xml/cbg.c +76 -0
  7. data/ext/xml/extconf.rb +95 -0
  8. data/ext/xml/libxml.c +86 -0
  9. data/ext/xml/libxml.h +79 -0
  10. data/ext/xml/ruby_xml_attr.c +372 -0
  11. data/ext/xml/ruby_xml_attr.h +21 -0
  12. data/ext/xml/ruby_xml_attribute.c +224 -0
  13. data/ext/xml/ruby_xml_attribute.h +21 -0
  14. data/ext/xml/ruby_xml_document.c +1159 -0
  15. data/ext/xml/ruby_xml_document.h +27 -0
  16. data/ext/xml/ruby_xml_dtd.c +168 -0
  17. data/ext/xml/ruby_xml_dtd.h +17 -0
  18. data/ext/xml/ruby_xml_input_cbg.c +167 -0
  19. data/ext/xml/ruby_xml_input_cbg.h +21 -0
  20. data/ext/xml/ruby_xml_node.c +2052 -0
  21. data/ext/xml/ruby_xml_node.h +28 -0
  22. data/ext/xml/ruby_xml_node_set.c +197 -0
  23. data/ext/xml/ruby_xml_node_set.h +26 -0
  24. data/ext/xml/ruby_xml_ns.c +153 -0
  25. data/ext/xml/ruby_xml_ns.h +21 -0
  26. data/ext/xml/ruby_xml_parser.c +1363 -0
  27. data/ext/xml/ruby_xml_parser.h +31 -0
  28. data/ext/xml/ruby_xml_parser_context.c +715 -0
  29. data/ext/xml/ruby_xml_parser_context.h +22 -0
  30. data/ext/xml/ruby_xml_sax_parser.c +181 -0
  31. data/ext/xml/ruby_xml_sax_parser.h +21 -0
  32. data/ext/xml/ruby_xml_schema.c +142 -0
  33. data/ext/xml/ruby_xml_schema.h +16 -0
  34. data/ext/xml/ruby_xml_tree.c +43 -0
  35. data/ext/xml/ruby_xml_tree.h +12 -0
  36. data/ext/xml/ruby_xml_xinclude.c +20 -0
  37. data/ext/xml/ruby_xml_xinclude.h +13 -0
  38. data/ext/xml/ruby_xml_xpath.c +357 -0
  39. data/ext/xml/ruby_xml_xpath.h +24 -0
  40. data/ext/xml/ruby_xml_xpath_context.c +124 -0
  41. data/ext/xml/ruby_xml_xpath_context.h +24 -0
  42. data/ext/xml/ruby_xml_xpointer.c +100 -0
  43. data/ext/xml/ruby_xml_xpointer.h +27 -0
  44. data/ext/xml/ruby_xml_xpointer_context.c +22 -0
  45. data/ext/xml/ruby_xml_xpointer_context.h +18 -0
  46. data/tests/copy_bug.rb +21 -0
  47. data/tests/dtd-test.rb +24 -0
  48. data/tests/model/default_validation_bug.rb +0 -0
  49. data/tests/model/rubynet.xml +78 -0
  50. data/tests/model/rubynet_project +13 -0
  51. data/tests/model/xinclude.xml +5 -0
  52. data/tests/runner.rb +13 -0
  53. data/tests/schema-test.rb +74 -0
  54. data/tests/tc_default_validation.rb +0 -0
  55. data/tests/tc_xml_document.rb +51 -0
  56. data/tests/tc_xml_document_write.rb +25 -0
  57. data/tests/tc_xml_document_write2.rb +55 -0
  58. data/tests/tc_xml_document_write3.rb +97 -0
  59. data/tests/tc_xml_node.rb +59 -0
  60. data/tests/tc_xml_node2.rb +26 -0
  61. data/tests/tc_xml_node_set.rb +25 -0
  62. data/tests/tc_xml_node_xlink.rb +28 -0
  63. data/tests/tc_xml_parser.rb +175 -0
  64. data/tests/tc_xml_parser2.rb +17 -0
  65. data/tests/tc_xml_parser3.rb +23 -0
  66. data/tests/tc_xml_parser4.rb +33 -0
  67. data/tests/tc_xml_parser5.rb +27 -0
  68. data/tests/tc_xml_parser6.rb +23 -0
  69. data/tests/tc_xml_parser7.rb +28 -0
  70. data/tests/tc_xml_parser_context.rb +89 -0
  71. data/tests/tc_xml_xinclude.rb +30 -0
  72. data/tests/tc_xml_xpath.rb +23 -0
  73. data/tests/tc_xml_xpointer.rb +78 -0
  74. metadata +144 -0
@@ -0,0 +1,21 @@
1
+ /* $Id: ruby_xml_attr.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __RUBY_XML_ATTR__
6
+ #define __RUBY_XML_ATTR__
7
+
8
+ extern VALUE cXMLAttr;
9
+
10
+ typedef struct ruby_xml_attr {
11
+ xmlAttrPtr attr;
12
+ VALUE xd;
13
+ int is_ptr;
14
+ } ruby_xml_attr;
15
+
16
+ void ruby_xml_attr_free(ruby_xml_attr *rxn);
17
+ void ruby_init_xml_attr(void);
18
+ VALUE ruby_xml_attr_new(VALUE class, VALUE xd, xmlAttrPtr attr);
19
+ VALUE ruby_xml_attr_new2(VALUE class, VALUE xd, xmlAttrPtr attr);
20
+ VALUE ruby_xml_attr_name_get(VALUE self);
21
+ #endif
@@ -0,0 +1,224 @@
1
+ /* $Id: ruby_xml_attribute.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "libxml.h"
6
+ #include "ruby_xml_attribute.h"
7
+
8
+ VALUE cXMLAttribute;
9
+
10
+ // TODO Wtf is this about? It's not referenced outside this file AFAIK...
11
+
12
+ VALUE
13
+ ruby_xml_attribute_child_get(VALUE self) {
14
+ ruby_xml_attribute *rxa;
15
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
16
+ if (rxa->attribute->children == NULL)
17
+ return(Qnil);
18
+ else
19
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->children));
20
+ }
21
+
22
+
23
+ VALUE
24
+ ruby_xml_attribute_children_q(VALUE self) {
25
+ ruby_xml_attribute *rxa;
26
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
27
+ if (rxa->attribute->children == NULL)
28
+ return(Qfalse);
29
+ else
30
+ return(Qtrue);
31
+ }
32
+
33
+
34
+ VALUE
35
+ ruby_xml_attribute_default_get(VALUE self) {
36
+ ruby_xml_attribute *rxa;
37
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
38
+
39
+ if (rxa->attribute->defaultValue == NULL)
40
+ return(Qnil);
41
+ else
42
+ return(rb_str_new2((const char*)rxa->attribute->defaultValue));
43
+ }
44
+
45
+
46
+ VALUE
47
+ ruby_xml_attribute_element_get(VALUE self) {
48
+ ruby_xml_attribute *rxa;
49
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
50
+
51
+ if (rxa->attribute->elem == NULL)
52
+ return(Qnil);
53
+ else
54
+ return(rb_str_new2((const char*)rxa->attribute->elem));
55
+ }
56
+
57
+
58
+ void
59
+ ruby_xml_attribute_free(ruby_xml_attribute *rxa) {
60
+ if (rxa->attribute != NULL && !rxa->is_ptr) {
61
+ xmlUnlinkNode((xmlNodePtr)rxa->attribute);
62
+ xmlFreeNode((xmlNodePtr)rxa->attribute);
63
+ rxa->attribute = NULL;
64
+ }
65
+
66
+ free(rxa);
67
+ }
68
+
69
+
70
+ VALUE
71
+ ruby_xml_attribute_last_get(VALUE self) {
72
+ ruby_xml_attribute *rxa;
73
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
74
+ if (rxa->attribute->last == NULL)
75
+ return(Qnil);
76
+ else
77
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->last));
78
+ }
79
+
80
+
81
+ VALUE
82
+ ruby_xml_attribute_last_q(VALUE self) {
83
+ ruby_xml_attribute *rxa;
84
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
85
+ if (rxa->attribute->last == NULL)
86
+ return(Qfalse);
87
+ else
88
+ return(Qtrue);
89
+ }
90
+
91
+
92
+ static void
93
+ ruby_xml_attribute_mark(ruby_xml_attribute *rxa) {
94
+ if (rxa == NULL) return;
95
+ if (!NIL_P(rxa->xd)) rb_gc_mark(rxa->xd);
96
+ }
97
+
98
+
99
+ VALUE
100
+ ruby_xml_attribute_name_get(VALUE self) {
101
+ ruby_xml_attribute *rxa;
102
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
103
+
104
+ if (rxa->attribute->name == NULL)
105
+ return(Qnil);
106
+ else
107
+ return(rb_str_new2((const char*)rxa->attribute->name));
108
+ }
109
+
110
+
111
+ VALUE
112
+ ruby_xml_attribute_new(VALUE class, VALUE xd, xmlAttributePtr attribute) {
113
+ ruby_xml_attribute *rxa;
114
+
115
+ rxa = ALLOC(ruby_xml_attribute);
116
+ rxa->is_ptr = 0;
117
+ rxa->attribute = attribute;
118
+ if (NIL_P(xd))
119
+ rxa->xd = Qnil;
120
+ else
121
+ rxa->xd = xd;
122
+ return(Data_Wrap_Struct(class, ruby_xml_attribute_mark,
123
+ ruby_xml_attribute_free, rxa));
124
+ }
125
+
126
+
127
+ VALUE
128
+ ruby_xml_attribute_new2(VALUE class, VALUE xd, xmlAttributePtr attribute) {
129
+ ruby_xml_attribute *rxa;
130
+
131
+ rxa = ALLOC(ruby_xml_attribute);
132
+ rxa->is_ptr = 1;
133
+ rxa->attribute = attribute;
134
+ if (NIL_P(xd))
135
+ rxa->xd = Qnil;
136
+ else
137
+ rxa->xd = xd;
138
+ return(Data_Wrap_Struct(class, ruby_xml_attribute_mark,
139
+ ruby_xml_attribute_free, rxa));
140
+ }
141
+
142
+
143
+ VALUE
144
+ ruby_xml_attribute_next_get(VALUE self) {
145
+ ruby_xml_attribute *rxa;
146
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
147
+ if (rxa->attribute->next == NULL)
148
+ return(Qnil);
149
+ else
150
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->next));
151
+ }
152
+
153
+
154
+ VALUE
155
+ ruby_xml_attribute_next_q(VALUE self) {
156
+ ruby_xml_attribute *rxa;
157
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
158
+ if (rxa->attribute->next == NULL)
159
+ return(Qfalse);
160
+ else
161
+ return(Qtrue);
162
+ }
163
+
164
+
165
+ VALUE
166
+ ruby_xml_attribute_node_type_name(VALUE self) {
167
+ return(rb_str_new2("attribute"));
168
+ }
169
+
170
+
171
+ VALUE
172
+ ruby_xml_attribute_prefix_get(VALUE self) {
173
+ ruby_xml_attribute *rxa;
174
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
175
+
176
+ if (rxa->attribute->prefix == NULL)
177
+ return(Qnil);
178
+ else
179
+ return(rb_str_new2((const char*)rxa->attribute->prefix));
180
+ }
181
+
182
+
183
+ VALUE
184
+ ruby_xml_attribute_prev_get(VALUE self) {
185
+ ruby_xml_attribute *rxa;
186
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
187
+ if (rxa->attribute->prev == NULL)
188
+ return(Qnil);
189
+ else
190
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->prev));
191
+ }
192
+
193
+ VALUE
194
+ ruby_xml_attribute_prev_q(VALUE self) {
195
+ ruby_xml_attribute *rxa;
196
+ Data_Get_Struct(self, ruby_xml_attribute, rxa);
197
+ if (rxa->attribute->prev == NULL)
198
+ return(Qfalse);
199
+ else
200
+ return(Qtrue);
201
+ }
202
+
203
+ // Rdoc maybe doesn't need to know
204
+ // #ifdef RDOC_NEVER_DEFINED
205
+ // mXML = rb_define_module("XML");
206
+ // #endif
207
+
208
+ void
209
+ ruby_init_xml_attribute(void) {
210
+ cXMLAttribute = rb_define_class_under(mXML, "Attribute", rb_cObject);
211
+ rb_define_method(cXMLAttribute, "child", ruby_xml_attribute_child_get, 0);
212
+ rb_define_method(cXMLAttribute, "children?", ruby_xml_attribute_children_q, 0);
213
+ rb_define_method(cXMLAttribute, "default", ruby_xml_attribute_default_get, 0);
214
+ rb_define_method(cXMLAttribute, "element", ruby_xml_attribute_element_get, 0);
215
+ rb_define_method(cXMLAttribute, "last", ruby_xml_attribute_last_get, 0);
216
+ rb_define_method(cXMLAttribute, "last?", ruby_xml_attribute_last_q, 0);
217
+ rb_define_method(cXMLAttribute, "node_type_name", ruby_xml_attribute_node_type_name, 0);
218
+ rb_define_method(cXMLAttribute, "name", ruby_xml_attribute_name_get, 0);
219
+ rb_define_method(cXMLAttribute, "next", ruby_xml_attribute_next_get, 0);
220
+ rb_define_method(cXMLAttribute, "next?", ruby_xml_attribute_next_q, 0);
221
+ rb_define_method(cXMLAttribute, "prefix", ruby_xml_attribute_prefix_get, 0);
222
+ rb_define_method(cXMLAttribute, "prev", ruby_xml_attribute_prev_get, 0);
223
+ rb_define_method(cXMLAttribute, "prev?", ruby_xml_attribute_prev_q, 0);
224
+ }
@@ -0,0 +1,21 @@
1
+ /* $Id: ruby_xml_attribute.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __RUBY_XML_ATTRIBUTE__
6
+ #define __RUBY_XML_ATTRIBUTE__
7
+
8
+ extern VALUE cXMLAttribute;
9
+
10
+ typedef struct ruby_xml_attribute {
11
+ xmlAttributePtr attribute;
12
+ VALUE xd;
13
+ int is_ptr;
14
+ } ruby_xml_attribute;
15
+
16
+ void ruby_xml_attribute_free(ruby_xml_attribute *rxa);
17
+ void ruby_init_xml_attribute(void);
18
+ VALUE ruby_xml_attribute_new(VALUE class, VALUE xd, xmlAttributePtr attribute);
19
+ VALUE ruby_xml_attribute_new2(VALUE class, VALUE xd, xmlAttributePtr attribute);
20
+ VALUE ruby_xml_attribute_name_get(VALUE self);
21
+ #endif
@@ -0,0 +1,1159 @@
1
+ /* $Id: ruby_xml_document.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "libxml.h"
6
+ #include "ruby_xml_document.h"
7
+
8
+ VALUE cXMLDocument;
9
+
10
+ /*
11
+ * call-seq:
12
+ * document.compression => num
13
+ *
14
+ * Obtain this document's compression mode identifier.
15
+ */
16
+ VALUE
17
+ ruby_xml_document_compression_get(VALUE self) {
18
+ #ifdef HAVE_ZLIB_H
19
+ ruby_xml_document *rxd;
20
+ int compmode;
21
+ Data_Get_Struct(self, ruby_xml_document, rxd);
22
+
23
+ compmode = xmlGetDocCompressMode(rxd->doc);
24
+ if (compmode == -1)
25
+ return(Qnil);
26
+ else
27
+ return(INT2NUM(compmode));
28
+ #else
29
+ rb_warn("libxml not compiled with zlib support");
30
+ return(Qfalse);
31
+ #endif
32
+ }
33
+
34
+
35
+ /*
36
+ * call-seq:
37
+ * document.compression = num
38
+ *
39
+ * Set this document's compression mode.
40
+ */
41
+ VALUE
42
+ ruby_xml_document_compression_set(VALUE self, VALUE num) {
43
+ #ifdef HAVE_ZLIB_H
44
+ ruby_xml_document *rxd;
45
+ int compmode;
46
+ Check_Type(num, T_FIXNUM);
47
+ Data_Get_Struct(self, ruby_xml_document, rxd);
48
+
49
+ if (rxd->doc == NULL) {
50
+ return(Qnil);
51
+ } else {
52
+ xmlSetDocCompressMode(rxd->doc, NUM2INT(num));
53
+
54
+ compmode = xmlGetDocCompressMode(rxd->doc);
55
+ if (compmode == -1)
56
+ return(Qnil);
57
+ else
58
+ return(INT2NUM(compmode));
59
+ }
60
+ #else
61
+ rb_warn("libxml compiled without zlib support");
62
+ return(Qfalse);
63
+ #endif
64
+ }
65
+
66
+
67
+ /*
68
+ * call-seq:
69
+ * document.compression? => (true|false)
70
+ *
71
+ * Determine whether this document is compressed.
72
+ */
73
+ VALUE
74
+ ruby_xml_document_compression_q(VALUE self) {
75
+ #ifdef HAVE_ZLIB_H
76
+ ruby_xml_document *rxd;
77
+ Data_Get_Struct(self, ruby_xml_document, rxd);
78
+
79
+ if (rxd->doc->compression != -1)
80
+ return(Qtrue);
81
+ else
82
+ return(Qfalse);
83
+ #else
84
+ rb_warn("libxml compiled without zlib support");
85
+ return(Qfalse);
86
+ #endif
87
+ }
88
+
89
+
90
+ /*
91
+ * call-seq:
92
+ * document.child => node
93
+ *
94
+ * Get this document's child node.
95
+ */
96
+ VALUE
97
+ ruby_xml_document_child_get(VALUE self) {
98
+ ruby_xml_document *rxd;
99
+ ruby_xml_node *rxn;
100
+ VALUE node;
101
+
102
+ Data_Get_Struct(self, ruby_xml_document, rxd);
103
+
104
+ if (rxd->doc->children == NULL)
105
+ return(Qnil);
106
+
107
+ node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->children);
108
+ Data_Get_Struct(node, ruby_xml_node, rxn);
109
+ rxn->xd = self;
110
+ return(node);
111
+ }
112
+
113
+
114
+ /*
115
+ * call-seq:
116
+ * document.child? => (true|false)
117
+ *
118
+ * Determine whether this document has a child node.
119
+ */
120
+ VALUE
121
+ ruby_xml_document_child_q(VALUE self) {
122
+ ruby_xml_document *rxd;
123
+ Data_Get_Struct(self, ruby_xml_document, rxd);
124
+
125
+ if (rxd->doc->children == NULL)
126
+ return(Qfalse);
127
+ else
128
+ return(Qtrue);
129
+ }
130
+
131
+
132
+ /*
133
+ * call-seq:
134
+ * document.dump([stream]) => true
135
+ *
136
+ * Dump this document's XML to the specified IO stream.
137
+ * If no stream is specified, stdout is used.
138
+ */
139
+ VALUE
140
+ ruby_xml_document_dump(int argc, VALUE *argv, VALUE self) {
141
+ OpenFile *fptr;
142
+ VALUE io;
143
+ FILE *out;
144
+ ruby_xml_document *rxd;
145
+
146
+ Data_Get_Struct(self, ruby_xml_document, rxd);
147
+ if (rxd->doc == NULL)
148
+ return(Qnil);
149
+
150
+ switch (argc) {
151
+ case 0:
152
+ io = rb_stdout;
153
+ break;
154
+ case 1:
155
+ io = argv[0];
156
+ if (!rb_obj_is_kind_of(io, rb_cIO))
157
+ rb_raise(rb_eTypeError, "need an IO object");
158
+ break;
159
+ default:
160
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
161
+ }
162
+
163
+ GetOpenFile(io, fptr);
164
+ rb_io_check_writable(fptr);
165
+ out = GetWriteFile(fptr);
166
+ xmlDocDump(out, rxd->doc);
167
+ return(Qtrue);
168
+ }
169
+
170
+
171
+ /*
172
+ * call-seq:
173
+ * document.debug_dump([stream]) => true
174
+ *
175
+ * Debug version of dump.
176
+ */
177
+ VALUE
178
+ ruby_xml_document_debug_dump(int argc, VALUE *argv, VALUE self) {
179
+ #ifdef LIBXML_DEBUG_ENABLED
180
+ OpenFile *fptr;
181
+ VALUE io;
182
+ FILE *out;
183
+ ruby_xml_document *rxd;
184
+
185
+ Data_Get_Struct(self, ruby_xml_document, rxd);
186
+ if (rxd->doc == NULL)
187
+ return(Qnil);
188
+
189
+ switch (argc) {
190
+ case 0:
191
+ io = rb_stderr;
192
+ break;
193
+ case 1:
194
+ io = argv[0];
195
+ if (!rb_obj_is_kind_of(io, rb_cIO))
196
+ rb_raise(rb_eTypeError, "need an IO object");
197
+ break;
198
+ default:
199
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
200
+ }
201
+
202
+ GetOpenFile(io, fptr);
203
+ rb_io_check_writable(fptr);
204
+ out = GetWriteFile(fptr);
205
+ xmlDebugDumpDocument(out, rxd->doc);
206
+ return(Qtrue);
207
+ #else
208
+ rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
209
+ return(Qfalse);
210
+ #endif
211
+ }
212
+
213
+
214
+ /*
215
+ * call-seq:
216
+ * document.debug_dump_head([stream]) => true
217
+ *
218
+ * Debug-dump this document's header to the specified IO stream.
219
+ * If no stream is specified, stdout is used.
220
+ */
221
+ VALUE
222
+ ruby_xml_document_debug_dump_head(int argc, VALUE *argv, VALUE self) {
223
+ #ifdef LIBXML_DEBUG_ENABLED
224
+ OpenFile *fptr;
225
+ VALUE io;
226
+ FILE *out;
227
+ ruby_xml_document *rxd;
228
+
229
+ Data_Get_Struct(self, ruby_xml_document, rxd);
230
+ if (rxd->doc == NULL)
231
+ return(Qnil);
232
+
233
+ switch (argc) {
234
+ case 0:
235
+ io = rb_stdout;
236
+ break;
237
+ case 1:
238
+ io = argv[0];
239
+ if (!rb_obj_is_kind_of(io, rb_cIO))
240
+ rb_raise(rb_eTypeError, "need an IO object");
241
+ break;
242
+ default:
243
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
244
+ }
245
+
246
+ GetOpenFile(io, fptr);
247
+ rb_io_check_writable(fptr);
248
+ out = GetWriteFile(fptr);
249
+ xmlDebugDumpDocumentHead(out, rxd->doc);
250
+ return(Qtrue);
251
+ #else
252
+ rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
253
+ return(Qfalse);
254
+ #endif
255
+ }
256
+
257
+
258
+ /*
259
+ * call-seq:
260
+ * document.format_dump([stream], [spacing]) => true
261
+ *
262
+ * Dump this document's formatted XML to the specified IO stream.
263
+ * If no stream is specified, stdout is used. If spacing is
264
+ * specified, it must be a boolean that determines whether
265
+ * spacing is used.
266
+ */
267
+ VALUE
268
+ ruby_xml_document_format_dump(int argc, VALUE *argv, VALUE self) {
269
+ OpenFile *fptr;
270
+ VALUE bool, io;
271
+ FILE *out;
272
+ ruby_xml_document *rxd;
273
+ int size, spacing;
274
+
275
+ Data_Get_Struct(self, ruby_xml_document, rxd);
276
+ if (rxd->doc == NULL)
277
+ return(Qnil);
278
+
279
+ switch (argc) {
280
+ case 0:
281
+ io = rb_stdout;
282
+ spacing = 1;
283
+ break;
284
+ case 1:
285
+ io = argv[0];
286
+ if (!rb_obj_is_kind_of(io, rb_cIO))
287
+ rb_raise(rb_eTypeError, "need an IO object");
288
+ spacing = 1;
289
+ break;
290
+ case 2:
291
+ io = argv[0];
292
+ if (!rb_obj_is_kind_of(io, rb_cIO))
293
+ rb_raise(rb_eTypeError, "need an IO object");
294
+ bool = argv[1];
295
+ if (TYPE(bool) == T_TRUE)
296
+ spacing = 1;
297
+ else if (TYPE(bool) == T_FALSE)
298
+ spacing = 0;
299
+ else
300
+ rb_raise(rb_eTypeError, "incorect argument type, second argument must be bool");
301
+
302
+ break;
303
+ default:
304
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
305
+ }
306
+
307
+ GetOpenFile(io, fptr);
308
+ rb_io_check_writable(fptr);
309
+ out = GetWriteFile(fptr);
310
+ size = xmlDocFormatDump(out, rxd->doc, spacing);
311
+ return(INT2NUM(size));
312
+ }
313
+
314
+
315
+ /*
316
+ * call-seq:
317
+ * document.debug_format_dump([stream]) => true
318
+ *
319
+ * *Deprecated* in favour of format_dump.
320
+ */
321
+ VALUE
322
+ ruby_xml_document_debug_format_dump(int argc, VALUE *argv, VALUE self) {
323
+ rb_warn("debug_format_dump has been deprecaited, use format_dump instead");
324
+ return(ruby_xml_document_format_dump(argc, argv, self));
325
+ }
326
+
327
+
328
+ /*
329
+ * call-seq:
330
+ * document.encoding => "encoding"
331
+ *
332
+ * Obtain the encoding specified by this document.
333
+ */
334
+ VALUE
335
+ ruby_xml_document_encoding_get(VALUE self) {
336
+ ruby_xml_document *rxd;
337
+ Data_Get_Struct(self, ruby_xml_document, rxd);
338
+ if (rxd->doc->encoding == NULL)
339
+ return(Qnil);
340
+ else
341
+ return(rb_str_new2((const char*)rxd->doc->encoding));
342
+ }
343
+
344
+
345
+ /*
346
+ * call-seq:
347
+ * document.encoding = "encoding"
348
+ *
349
+ * Set the encoding for this document.
350
+ */
351
+ VALUE
352
+ ruby_xml_document_encoding_set(VALUE self, VALUE encoding) {
353
+ ruby_xml_document *rxd;
354
+
355
+ Check_Type(encoding, T_STRING);
356
+ Data_Get_Struct(self, ruby_xml_document, rxd);
357
+ rxd->doc->encoding = (xmlChar*)ruby_strdup(StringValuePtr(encoding));
358
+ return(ruby_xml_document_encoding_get(self));
359
+ }
360
+
361
+
362
+ /*
363
+ * call-seq:
364
+ * document.filename => "filename"
365
+ *
366
+ * Obtain the filename this document was read from.
367
+ */
368
+ VALUE
369
+ ruby_xml_document_filename_get(VALUE self) {
370
+ ruby_xml_document *rxd;
371
+ rx_file_data *data;
372
+
373
+ Data_Get_Struct(self, ruby_xml_document, rxd);
374
+ if (rxd->data == NULL)
375
+ return(Qnil);
376
+
377
+ switch (rxd->data_type) {
378
+ case RUBY_LIBXML_SRC_TYPE_NULL:
379
+ return(Qnil);
380
+ case RUBY_LIBXML_SRC_TYPE_FILE:
381
+ data = (rx_file_data *)rxd->data;
382
+ return(data->filename);
383
+ default:
384
+ rb_fatal("Unknown document type in libxml");
385
+ }
386
+
387
+ return(Qnil);
388
+ }
389
+
390
+
391
+ /*
392
+ * call-seq:
393
+ * document.find(xpath_expr, [namespace]) => nodeset
394
+ *
395
+ * Find nodes matching the specified xpath expression, optionally
396
+ * using the specified namespace. Returns an XML::Node::Set.
397
+ */
398
+ VALUE
399
+ ruby_xml_document_find(int argc, VALUE *argv, VALUE self) {
400
+ int i, vargc;
401
+ VALUE *vargv;
402
+
403
+ if (argc > 2 || argc < 1)
404
+ rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
405
+
406
+ vargc = argc + 1;
407
+ vargv = ALLOC_N(VALUE, vargc + 1);
408
+ vargv[0] = ruby_xml_document_root_get(self);
409
+ for (i = 0; i<argc; i++)
410
+ vargv[i + 1] = argv[i];
411
+
412
+ return(ruby_xml_xpath_find2(vargc, vargv));
413
+ }
414
+
415
+
416
+ void
417
+ ruby_xml_document_free(ruby_xml_document *rxd) {
418
+ void *data;
419
+
420
+ if (rxd->doc != NULL && !rxd->is_ptr) {
421
+ xmlFreeDoc(rxd->doc);
422
+ ruby_xml_parser_count--;
423
+ rxd->doc = NULL;
424
+ }
425
+
426
+ if (ruby_xml_parser_count == 0)
427
+ xmlCleanupParser();
428
+
429
+ switch(rxd->data_type) {
430
+ case RUBY_LIBXML_SRC_TYPE_NULL:
431
+ break;
432
+ case RUBY_LIBXML_SRC_TYPE_FILE:
433
+ data = (void*)(rx_file_data *)rxd->data;
434
+ free((rx_file_data *)data);
435
+ break;
436
+ case RUBY_LIBXML_SRC_TYPE_STRING:
437
+ data = (void*)(rx_string_data *)rxd->data;
438
+ free((rx_string_data *)data);
439
+ break;
440
+ case RUBY_LIBXML_SRC_TYPE_IO:
441
+ data = (void*)(rx_io_data *)rxd->data;
442
+ free((rx_io_data *)data);
443
+ break;
444
+ default:
445
+ rb_fatal("Unknown data type, %d", rxd->data_type);
446
+ }
447
+
448
+ free(rxd);
449
+ }
450
+
451
+
452
+ /*
453
+ * call-seq:
454
+ * XML::Document.new(xml_version = 1.0) => document
455
+ *
456
+ * Create a new XML::Document, optionally specifying the
457
+ * XML version.
458
+ */
459
+ VALUE
460
+ ruby_xml_document_initialize(int argc, VALUE *argv, VALUE class) {
461
+ VALUE docobj, xmlver;
462
+
463
+ switch (argc) {
464
+ case 0:
465
+ xmlver = rb_str_new2("1.0");
466
+ break;
467
+ case 1:
468
+ rb_scan_args(argc, argv, "01", &xmlver);
469
+ break;
470
+ default:
471
+ rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
472
+ }
473
+
474
+ docobj = ruby_xml_document_new2(cXMLDocument, xmlver);
475
+ return(docobj);
476
+ }
477
+
478
+
479
+ /*
480
+ * call-seq:
481
+ * document.last => node
482
+ *
483
+ * Obtain the last node.
484
+ */
485
+ VALUE
486
+ ruby_xml_document_last_get(VALUE self) {
487
+ ruby_xml_document *rxd;
488
+ ruby_xml_node *rxn;
489
+ VALUE node;
490
+
491
+ Data_Get_Struct(self, ruby_xml_document, rxd);
492
+
493
+ if (rxd->doc->last == NULL)
494
+ return(Qnil);
495
+
496
+ node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->last);
497
+ Data_Get_Struct(node, ruby_xml_node, rxn);
498
+ rxn->xd = self;
499
+ return(node);
500
+ }
501
+
502
+
503
+ /*
504
+ * call-seq:
505
+ * document.last? => (true|false)
506
+ *
507
+ * Determine whether there is a last node.
508
+ */
509
+ VALUE
510
+ ruby_xml_document_last_q(VALUE self) {
511
+ ruby_xml_document *rxd;
512
+ Data_Get_Struct(self, ruby_xml_document, rxd);
513
+
514
+ if (rxd->doc->last == NULL)
515
+ return(Qfalse);
516
+ else
517
+ return(Qtrue);
518
+ }
519
+
520
+
521
+ static void
522
+ ruby_xml_document_mark(ruby_xml_document *rxd) {
523
+ if (rxd == NULL) return;
524
+ if (!NIL_P(rxd->xmlver)) rb_gc_mark(rxd->xmlver);
525
+ }
526
+
527
+
528
+ VALUE
529
+ ruby_xml_document_new(VALUE class, xmlDocPtr doc) {
530
+ ruby_xml_document *rxd;
531
+
532
+ rxd = ALLOC(ruby_xml_document);
533
+ ruby_xml_parser_count++;
534
+
535
+ rxd->data = NULL;
536
+ rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
537
+ rxd->doc = doc;
538
+ rxd->is_ptr = 0;
539
+ rxd->xmlver = Qnil;
540
+
541
+ return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
542
+ ruby_xml_document_free, rxd));
543
+ }
544
+
545
+
546
+ VALUE
547
+ ruby_xml_document_new2(VALUE class, VALUE xmlver) {
548
+ ruby_xml_document *rxd;
549
+
550
+ Check_Type(xmlver, T_STRING);
551
+ rxd = ALLOC(ruby_xml_document);
552
+ ruby_xml_parser_count++;
553
+
554
+ rxd->data = NULL;
555
+ rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
556
+ rxd->doc = xmlNewDoc((xmlChar*)StringValuePtr(xmlver));
557
+ rxd->is_ptr = 0;
558
+ rxd->xmlver = xmlver;
559
+
560
+ if (rxd->doc == NULL)
561
+ rb_fatal("bad");
562
+
563
+ return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
564
+ ruby_xml_document_free, rxd));
565
+ }
566
+
567
+
568
+ VALUE
569
+ ruby_xml_document_new3(VALUE class) {
570
+ return(ruby_xml_document_new2(class, rb_str_new2("1.0")));
571
+ }
572
+
573
+
574
+ VALUE
575
+ ruby_xml_document_new4(VALUE class, xmlDocPtr doc) {
576
+ ruby_xml_document *rxd;
577
+
578
+ rxd = ALLOC(ruby_xml_document);
579
+
580
+ rxd->data = NULL;
581
+ rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
582
+ rxd->doc = doc;
583
+ rxd->is_ptr = 1;
584
+ rxd->xmlver = Qnil;
585
+
586
+ return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
587
+ ruby_xml_document_free, rxd));
588
+ }
589
+
590
+
591
+ /*
592
+ * call-seq:
593
+ * XML::Document.file(filename) => document
594
+ *
595
+ * Create a new XML::Document by parsing the specified
596
+ * file.
597
+ */
598
+ VALUE
599
+ ruby_xml_document_new_file(VALUE class, VALUE filename) {
600
+ VALUE parser;
601
+
602
+ parser = ruby_xml_parser_new(cXMLParser);
603
+ ruby_xml_parser_filename_set(parser, filename);
604
+ return(ruby_xml_parser_parse(parser));
605
+ }
606
+
607
+
608
+ /*
609
+ * call-seq:
610
+ * document.next => node
611
+ *
612
+ * Obtain the next node.
613
+ */
614
+ VALUE
615
+ ruby_xml_document_next_get(VALUE self) {
616
+ ruby_xml_document *rxd;
617
+ ruby_xml_node *rxn;
618
+ VALUE node;
619
+
620
+ Data_Get_Struct(self, ruby_xml_document, rxd);
621
+
622
+ if (rxd->doc->next == NULL)
623
+ return(Qnil);
624
+
625
+ node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->next);
626
+ Data_Get_Struct(node, ruby_xml_node, rxn);
627
+ rxn->xd = self;
628
+ return(node);
629
+ }
630
+
631
+
632
+ /*
633
+ * call-seq:
634
+ * document.next? => (true|false)
635
+ *
636
+ * Determine whether there is a next node.
637
+ */
638
+ VALUE
639
+ ruby_xml_document_next_q(VALUE self) {
640
+ ruby_xml_document *rxd;
641
+ Data_Get_Struct(self, ruby_xml_document, rxd);
642
+
643
+ if (rxd->doc->next == NULL)
644
+ return(Qfalse);
645
+ else
646
+ return(Qtrue);
647
+ }
648
+
649
+
650
+ /*
651
+ * call-seq:
652
+ * document.parent => node
653
+ *
654
+ * Obtain the parent node.
655
+ */
656
+ VALUE
657
+ ruby_xml_document_parent_get(VALUE self) {
658
+ ruby_xml_document *rxd;
659
+ ruby_xml_node *rxn;
660
+ VALUE node;
661
+
662
+ Data_Get_Struct(self, ruby_xml_document, rxd);
663
+
664
+ if (rxd->doc->parent == NULL)
665
+ return(Qnil);
666
+
667
+ node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->parent);
668
+ Data_Get_Struct(node, ruby_xml_node, rxn);
669
+ rxn->xd = self;
670
+ return(node);
671
+ }
672
+
673
+
674
+ /*
675
+ * call-seq:
676
+ * document.parent? => (true|false)
677
+ *
678
+ * Determine whether there is a parent node.
679
+ */
680
+ VALUE
681
+ ruby_xml_document_parent_q(VALUE self) {
682
+ ruby_xml_document *rxd;
683
+ Data_Get_Struct(self, ruby_xml_document, rxd);
684
+
685
+ if (rxd->doc->parent == NULL)
686
+ return(Qfalse);
687
+ else
688
+ return(Qtrue);
689
+ }
690
+
691
+
692
+ /*
693
+ * call-seq:
694
+ * document.prev => node
695
+ *
696
+ * Obtain the previous node.
697
+ */
698
+ VALUE
699
+ ruby_xml_document_prev_get(VALUE self) {
700
+ ruby_xml_document *rxd;
701
+ ruby_xml_node *rxn;
702
+ VALUE node;
703
+
704
+ Data_Get_Struct(self, ruby_xml_document, rxd);
705
+
706
+ if (rxd->doc->prev == NULL)
707
+ return(Qnil);
708
+
709
+ node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->prev);
710
+ Data_Get_Struct(node, ruby_xml_node, rxn);
711
+ rxn->xd = self;
712
+ return(node);
713
+ }
714
+
715
+
716
+ /*
717
+ * call-seq:
718
+ * document.prev? => (true|false)
719
+ *
720
+ * Determine whether there is a previous node.
721
+ */
722
+ VALUE
723
+ ruby_xml_document_prev_q(VALUE self) {
724
+ ruby_xml_document *rxd;
725
+ Data_Get_Struct(self, ruby_xml_document, rxd);
726
+
727
+ if (rxd->doc->prev == NULL)
728
+ return(Qfalse);
729
+ else
730
+ return(Qtrue);
731
+ }
732
+
733
+
734
+ /*
735
+ * call-seq:
736
+ * document["key"] => "value"
737
+ *
738
+ * Obtain the named property.
739
+ */
740
+ VALUE
741
+ ruby_xml_document_property_get(VALUE self, VALUE key) {
742
+ return(ruby_xml_node_property_get(ruby_xml_document_root_get(self), key));
743
+ }
744
+
745
+
746
+ /*
747
+ * call-seq:
748
+ * document["key"] = "value"
749
+ *
750
+ * Set the named property.
751
+ */
752
+ VALUE
753
+ ruby_xml_document_property_set(VALUE self, VALUE key, VALUE val) {
754
+ return(ruby_xml_node_property_set(ruby_xml_document_root_get(self), key, val));
755
+ }
756
+
757
+
758
+ /*
759
+ * call-seq:
760
+ * document.root => node
761
+ *
762
+ * Obtain the root node.
763
+ */
764
+ VALUE
765
+ ruby_xml_document_root_get(VALUE self) {
766
+ ruby_xml_document *rxd;
767
+ ruby_xml_node *rxn;
768
+ VALUE node;
769
+ xmlNodePtr root;
770
+
771
+ Data_Get_Struct(self, ruby_xml_document, rxd);
772
+ root = xmlDocGetRootElement(rxd->doc);
773
+
774
+ if (root == NULL)
775
+ return(Qnil);
776
+
777
+ node = ruby_xml_node_new2(cXMLNode, self, root);
778
+ Data_Get_Struct(node, ruby_xml_node, rxn);
779
+ rxn->xd = self;
780
+ return(node);
781
+ }
782
+
783
+
784
+ /*
785
+ * call-seq:
786
+ * document.root = node
787
+ *
788
+ * Set the root node.
789
+ */
790
+ VALUE
791
+ ruby_xml_document_root_set(VALUE self, VALUE node) {
792
+ ruby_xml_document *rxd;
793
+ ruby_xml_node *rxn;
794
+ VALUE retnode;
795
+ xmlNodePtr root;
796
+
797
+ if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
798
+ rb_raise(rb_eTypeError, "must pass an XML::Node type object");
799
+
800
+ Data_Get_Struct(self, ruby_xml_document, rxd);
801
+ Data_Get_Struct(node, ruby_xml_node, rxn);
802
+ ruby_xml_node_set_ptr(node, 1);
803
+ root = xmlDocSetRootElement(rxd->doc, rxn->node);
804
+ if (root == NULL)
805
+ return(Qnil);
806
+
807
+ retnode = ruby_xml_node_new2(cXMLNode, self, root);
808
+ return(retnode);
809
+ }
810
+
811
+
812
+ /*
813
+ * call-seq:
814
+ * document.save(format = false)
815
+ *
816
+ * Save this document to the file given by filename,
817
+ * optionally formatting the output.
818
+ */
819
+ VALUE
820
+ ruby_xml_document_save(int argc, VALUE *argv, VALUE self) {
821
+ ruby_xml_document *rxd;
822
+ const char *filename;
823
+ int format, len;
824
+
825
+ format = 0;
826
+ switch (argc) {
827
+ case 1:
828
+ break;
829
+ case 2:
830
+ if (TYPE(argv[1]) == T_TRUE)
831
+ format = 1;
832
+ else if (TYPE(argv[1]) == T_FALSE)
833
+ format = 0;
834
+ else
835
+ rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
836
+ break;
837
+ default:
838
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
839
+ }
840
+
841
+ Check_Type(argv[0], T_STRING);
842
+ filename = StringValuePtr(argv[0]);
843
+
844
+ Data_Get_Struct(self, ruby_xml_document, rxd);
845
+ len = xmlSaveFormatFileEnc(filename, rxd->doc, (const char*)rxd->doc->encoding, format);
846
+ if (len == -1)
847
+ rb_fatal("Unable to write out file");
848
+ else
849
+ return(INT2NUM(len));
850
+ }
851
+
852
+
853
+ /*
854
+ * call-seq:
855
+ * document.standalone? => (true|false)
856
+ *
857
+ * Determine whether this is a standalone document.
858
+ */
859
+ VALUE
860
+ ruby_xml_document_standalone_q(VALUE self) {
861
+ ruby_xml_document *rxd;
862
+ Data_Get_Struct(self, ruby_xml_document, rxd);
863
+ if (rxd->doc->standalone)
864
+ return(Qtrue);
865
+ else
866
+ return(Qfalse);
867
+ }
868
+
869
+
870
+ /*
871
+ * call-seq:
872
+ * document.to_s => "xml"
873
+ *
874
+ * Coerce this document to a string representation
875
+ * of it's XML.
876
+ */
877
+ VALUE
878
+ ruby_xml_document_to_s(int argc, VALUE *argv, VALUE self) {
879
+ ruby_xml_document *rxd;
880
+ xmlChar *result;
881
+ int format, len;
882
+
883
+ switch (argc) {
884
+ case 0:
885
+ format = 1;
886
+ break;
887
+ case 1:
888
+ if (TYPE(argv[0]) == T_TRUE)
889
+ format = 1;
890
+ else if (TYPE(argv[0]) == T_FALSE)
891
+ format = 0;
892
+ else
893
+ rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
894
+ break;
895
+ default:
896
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
897
+ }
898
+
899
+ Data_Get_Struct(self, ruby_xml_document, rxd);
900
+ if (rxd->doc == NULL) {
901
+ return(Qnil);
902
+ } else if (rxd->doc->encoding != NULL) {
903
+ if (format) {
904
+ xmlDocDumpFormatMemoryEnc(rxd->doc, &result, &len,
905
+ (const char*)rxd->doc->encoding, format);
906
+ } else {
907
+ xmlDocDumpMemoryEnc(rxd->doc, &result, &len,
908
+ (const char*)rxd->doc->encoding);
909
+ }
910
+ } else {
911
+ if (format)
912
+ xmlDocDumpFormatMemory(rxd->doc, &result, &len, format);
913
+ else
914
+ xmlDocDumpMemory(rxd->doc, &result, &len);
915
+ }
916
+
917
+ return(rb_str_new2((const char*)result));
918
+ }
919
+
920
+
921
+ /*
922
+ * call-seq:
923
+ * document.url => "url"
924
+ *
925
+ * Obtain this document's source URL, if any.
926
+ */
927
+ VALUE
928
+ ruby_xml_document_url_get(VALUE self) {
929
+ ruby_xml_document *rxd;
930
+ Data_Get_Struct(self, ruby_xml_document, rxd);
931
+ if (rxd->doc->URL == NULL)
932
+ return(Qnil);
933
+ else
934
+ return(rb_str_new2((const char*)rxd->doc->URL));
935
+ }
936
+
937
+
938
+ /*
939
+ * call-seq:
940
+ * document.version => "version"
941
+ *
942
+ * Obtain the XML version specified by this document.
943
+ */
944
+ VALUE
945
+ ruby_xml_document_version_get(VALUE self) {
946
+ ruby_xml_document *rxd;
947
+ Data_Get_Struct(self, ruby_xml_document, rxd);
948
+ if (rxd->doc->version == NULL)
949
+ return(Qnil);
950
+ else
951
+ return(rb_str_new2((const char*)rxd->doc->version));
952
+ }
953
+
954
+
955
+ /*
956
+ * call-seq:
957
+ * document.xinclude => num
958
+ *
959
+ * Process xinclude directives in this document.
960
+ */
961
+ VALUE
962
+ ruby_xml_document_xinclude(VALUE self) {
963
+ #ifdef LIBXML_XINCLUDE_ENABLED
964
+ ruby_xml_document *rxd;
965
+ int ret;
966
+
967
+ Data_Get_Struct(self, ruby_xml_document, rxd);
968
+ ret = xmlXIncludeProcess(rxd->doc);
969
+ if (ret >= 0)
970
+ return(INT2NUM(ret));
971
+ else
972
+ rb_raise(eXMLXIncludeError, "error processing xinclude directives in document");
973
+ #else
974
+ rb_warn("libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
975
+ return(Qfalse);
976
+ #endif
977
+ }
978
+
979
+ void
980
+ LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
981
+ {
982
+ if (rb_block_given_p()) {
983
+ char buff[1024];
984
+ snprintf(buff, 1024, msg, ap);
985
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
986
+ } else {
987
+ fprintf(stderr, "error -- found validity error: ");
988
+ fprintf(stderr, msg, ap);
989
+ }
990
+ }
991
+
992
+ void
993
+ LibXML_validity_warning(void * ctxt, const char * msg, va_list ap)
994
+ {
995
+ if (rb_block_given_p()) {
996
+ char buff[1024];
997
+ snprintf(buff, 1024, msg, ap);
998
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qfalse));
999
+ } else {
1000
+ fprintf(stderr, "warning -- found validity error: ");
1001
+ fprintf(stderr, msg, ap);
1002
+ }
1003
+ }
1004
+
1005
+ /*
1006
+ * call-seq:
1007
+ * document.validate(schema) => (true|false)
1008
+ *
1009
+ * Validate this document against the specified XML::Schema.
1010
+ */
1011
+ VALUE
1012
+ ruby_xml_document_validate_schema(VALUE self, VALUE schema) {
1013
+ xmlSchemaValidCtxtPtr vptr;
1014
+ ruby_xml_document *c_doc;
1015
+ ruby_xml_schema *c_schema;
1016
+ int is_invalid;
1017
+
1018
+ Data_Get_Struct(self, ruby_xml_document, c_doc);
1019
+ Data_Get_Struct(schema, ruby_xml_schema, c_schema);
1020
+
1021
+ vptr = xmlSchemaNewValidCtxt(c_schema->schema);
1022
+
1023
+ xmlSchemaSetValidErrors(vptr, (xmlSchemaValidityErrorFunc)LibXML_validity_error,
1024
+ (xmlSchemaValidityWarningFunc)LibXML_validity_warning, NULL);
1025
+
1026
+ is_invalid = xmlSchemaValidateDoc(vptr, c_doc->doc);
1027
+ xmlSchemaFreeValidCtxt(vptr);
1028
+ if (is_invalid) {
1029
+ return Qfalse;
1030
+ } else {
1031
+ return Qtrue;
1032
+ }
1033
+ }
1034
+
1035
+
1036
+ /*
1037
+ * call-seq:
1038
+ * document.validate(schema) => (true|false)
1039
+ *
1040
+ * Validate this document against the specified XML::DTD.
1041
+ */
1042
+ VALUE
1043
+ ruby_xml_document_validate_dtd(VALUE self, VALUE dtd) {
1044
+ xmlValidCtxt cvp;
1045
+ ruby_xml_document *c_doc;
1046
+ ruby_xml_dtd *c_dtd;
1047
+
1048
+ Data_Get_Struct(self, ruby_xml_document, c_doc);
1049
+ Data_Get_Struct(dtd, ruby_xml_dtd, c_dtd);
1050
+
1051
+ cvp.userData = NULL;
1052
+ cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
1053
+ cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
1054
+
1055
+ cvp.nodeNr = 0;
1056
+ cvp.nodeTab = NULL;
1057
+ cvp.vstateNr = 0;
1058
+ cvp.vstateTab = NULL;
1059
+
1060
+ if ( xmlValidateDtd(&cvp, c_doc->doc, c_dtd->dtd) )
1061
+ return(Qtrue);
1062
+ else
1063
+ return(Qfalse);
1064
+
1065
+ // int xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd)
1066
+ /*
1067
+ int
1068
+ validate(self, ...)
1069
+ xmlDocPtr self
1070
+ PREINIT:
1071
+ xmlValidCtxt cvp;
1072
+ xmlDtdPtr dtd;
1073
+ SV * dtd_sv;
1074
+ STRLEN n_a, len;
1075
+ CODE:
1076
+ LibXML_init_error();
1077
+ cvp.userData = (void*)PerlIO_stderr();
1078
+ cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
1079
+ cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
1080
+ // we need to initialize the node stack, because perl might
1081
+ // already messed it up.
1082
+ //
1083
+ cvp.nodeNr = 0;
1084
+ cvp.nodeTab = NULL;
1085
+ cvp.vstateNr = 0;
1086
+ cvp.vstateTab = NULL;
1087
+
1088
+ if (items > 1) {
1089
+ dtd_sv = ST(1);
1090
+ if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
1091
+ dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
1092
+ }
1093
+ else {
1094
+ croak("is_valid: argument must be a DTD object");
1095
+ }
1096
+ RETVAL = xmlValidateDtd(&cvp, self , dtd);
1097
+ }
1098
+ else {
1099
+ RETVAL = xmlValidateDocument(&cvp, self);
1100
+ }
1101
+ sv_2mortal(LibXML_error);
1102
+
1103
+ if (RETVAL == 0) {
1104
+ LibXML_croak_error();
1105
+ }
1106
+ OUTPUT:
1107
+ RETVAL
1108
+ */
1109
+ }
1110
+
1111
+ // Rdoc needs to know
1112
+ #ifdef RDOC_NEVER_DEFINED
1113
+ mXML = rb_define_module("XML");
1114
+ #endif
1115
+
1116
+ void
1117
+ ruby_init_xml_document(void) {
1118
+ cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
1119
+ rb_define_singleton_method(cXMLDocument, "file", ruby_xml_document_new_file, 1);
1120
+ rb_define_singleton_method(cXMLDocument, "new", ruby_xml_document_initialize, -1);
1121
+
1122
+ //rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
1123
+ //eDTDValidityWarning = rb_define_class_under(cXMLNode, "ValidityWarning", rb_eException);
1124
+ //eDTDValidityError = rb_define_class_under(cXMLNode, "ValidityWarning", rb_eException);
1125
+ rb_define_method(cXMLDocument, "[]", ruby_xml_document_property_get, 1);
1126
+ rb_define_method(cXMLDocument, "[]=", ruby_xml_document_property_set, 2);
1127
+ rb_define_method(cXMLDocument, "child", ruby_xml_document_child_get, 0);
1128
+ rb_define_method(cXMLDocument, "child?", ruby_xml_document_child_q, 0);
1129
+ rb_define_method(cXMLDocument, "compression", ruby_xml_document_compression_get, 0);
1130
+ rb_define_method(cXMLDocument, "compression=", ruby_xml_document_compression_set, 1);
1131
+ rb_define_method(cXMLDocument, "compression?", ruby_xml_document_compression_q, 0);
1132
+ rb_define_method(cXMLDocument, "dump", ruby_xml_document_dump, -1);
1133
+ rb_define_method(cXMLDocument, "debug_dump", ruby_xml_document_debug_dump, -1);
1134
+ rb_define_method(cXMLDocument, "debug_dump_head", ruby_xml_document_debug_dump_head, -1);
1135
+ rb_define_method(cXMLDocument, "debug_format_dump", ruby_xml_document_debug_format_dump, -1);
1136
+ rb_define_method(cXMLDocument, "encoding", ruby_xml_document_encoding_get, 0);
1137
+ rb_define_method(cXMLDocument, "encoding=", ruby_xml_document_encoding_set, 1);
1138
+ rb_define_method(cXMLDocument, "filename", ruby_xml_document_filename_get, 0);
1139
+ rb_define_method(cXMLDocument, "find", ruby_xml_document_find, -1);
1140
+ rb_define_method(cXMLDocument, "format_dump", ruby_xml_document_format_dump, -1);
1141
+ rb_define_method(cXMLDocument, "last", ruby_xml_document_last_get, 0);
1142
+ rb_define_method(cXMLDocument, "last?", ruby_xml_document_last_q, 0);
1143
+ rb_define_method(cXMLDocument, "next", ruby_xml_document_next_get, 0);
1144
+ rb_define_method(cXMLDocument, "next?", ruby_xml_document_next_q, 0);
1145
+ rb_define_method(cXMLDocument, "parent", ruby_xml_document_parent_get, 0);
1146
+ rb_define_method(cXMLDocument, "parent?", ruby_xml_document_parent_q, 0);
1147
+ rb_define_method(cXMLDocument, "prev", ruby_xml_document_prev_get, 0);
1148
+ rb_define_method(cXMLDocument, "prev?", ruby_xml_document_prev_q, 0);
1149
+ rb_define_method(cXMLDocument, "root", ruby_xml_document_root_get, 0);
1150
+ rb_define_method(cXMLDocument, "root=", ruby_xml_document_root_set, 1);
1151
+ rb_define_method(cXMLDocument, "save", ruby_xml_document_save, -1);
1152
+ rb_define_method(cXMLDocument, "standalone?", ruby_xml_document_standalone_q, 0);
1153
+ rb_define_method(cXMLDocument, "to_s", ruby_xml_document_to_s, -1);
1154
+ rb_define_method(cXMLDocument, "url", ruby_xml_document_url_get, 0);
1155
+ rb_define_method(cXMLDocument, "version", ruby_xml_document_version_get, 0);
1156
+ rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
1157
+ rb_define_method(cXMLDocument, "validate", ruby_xml_document_validate_dtd, 1);
1158
+ rb_define_method(cXMLDocument, "validate_schema", ruby_xml_document_validate_schema, 1);
1159
+ }