libxml-ruby 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
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
+ }