libxml-ruby 0.5.4 → 0.6.0

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