libxml-ruby 0.8.3-x86-mswin32-60 → 0.9.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. data/CHANGES +18 -0
  2. data/RAKEFILE +15 -39
  3. data/README +48 -47
  4. data/ext/libxml/libxml.c +847 -22
  5. data/ext/libxml/ruby_libxml.h +71 -95
  6. data/ext/libxml/ruby_xml_attr.c +500 -500
  7. data/ext/libxml/ruby_xml_attributes.c +1 -1
  8. data/ext/libxml/ruby_xml_document.c +1144 -1135
  9. data/ext/libxml/ruby_xml_document.h +4 -11
  10. data/ext/libxml/ruby_xml_dtd.c +27 -0
  11. data/ext/libxml/ruby_xml_encoding.c +164 -0
  12. data/ext/libxml/ruby_xml_encoding.h +13 -0
  13. data/ext/libxml/ruby_xml_error.c +941 -0
  14. data/ext/libxml/ruby_xml_error.h +13 -0
  15. data/ext/libxml/ruby_xml_html_parser.c +71 -387
  16. data/ext/libxml/ruby_xml_html_parser.h +1 -17
  17. data/ext/libxml/ruby_xml_input.c +179 -0
  18. data/ext/libxml/ruby_xml_input.h +18 -0
  19. data/ext/libxml/ruby_xml_input_cbg.c +17 -3
  20. data/ext/libxml/ruby_xml_node.c +1566 -1582
  21. data/ext/libxml/ruby_xml_node.h +1 -4
  22. data/ext/libxml/ruby_xml_ns.c +14 -3
  23. data/ext/libxml/ruby_xml_parser.c +164 -1398
  24. data/ext/libxml/ruby_xml_parser.h +5 -17
  25. data/ext/libxml/ruby_xml_parser_context.c +131 -169
  26. data/ext/libxml/ruby_xml_parser_context.h +2 -9
  27. data/ext/libxml/ruby_xml_reader.c +910 -945
  28. data/ext/libxml/ruby_xml_relaxng.c +32 -3
  29. data/ext/libxml/ruby_xml_sax_parser.c +106 -364
  30. data/ext/libxml/ruby_xml_sax_parser.h +1 -37
  31. data/ext/libxml/ruby_xml_schema.c +174 -145
  32. data/ext/libxml/ruby_xml_xinclude.c +9 -5
  33. data/ext/libxml/ruby_xml_xpath.c +25 -6
  34. data/ext/libxml/ruby_xml_xpath.h +1 -2
  35. data/ext/libxml/ruby_xml_xpath_context.c +17 -19
  36. data/ext/libxml/ruby_xml_xpath_object.c +60 -56
  37. data/ext/libxml/ruby_xml_xpointer.c +11 -5
  38. data/ext/libxml/sax_parser_callbacks.inc +42 -37
  39. data/ext/libxml/version.h +3 -3
  40. data/ext/mingw/Rakefile +20 -27
  41. data/ext/mingw/build.rake +41 -0
  42. data/{lib → ext/mingw}/libiconv-2.dll +0 -0
  43. data/ext/mingw/libxml2-2.dll +0 -0
  44. data/ext/mingw/libxml_ruby.dll.a +0 -0
  45. data/ext/mingw/libxml_ruby.so +0 -0
  46. data/ext/vc/libxml_ruby.vcproj +23 -15
  47. data/lib/libxml.rb +8 -2
  48. data/lib/libxml/document.rb +16 -4
  49. data/lib/libxml/error.rb +84 -0
  50. data/lib/libxml/hpricot.rb +76 -0
  51. data/lib/libxml/html_parser.rb +61 -0
  52. data/lib/libxml/node.rb +36 -25
  53. data/lib/libxml/parser.rb +312 -33
  54. data/lib/libxml/parser_context.rb +17 -0
  55. data/lib/libxml/properties.rb +15 -2
  56. data/lib/libxml/reader.rb +15 -0
  57. data/lib/libxml/sax_callbacks.rb +179 -0
  58. data/lib/libxml/sax_parser.rb +42 -0
  59. data/lib/libxml/tree.rb +1 -2
  60. data/lib/libxml/xpath_object.rb +12 -0
  61. data/test/model/atom.xml +4 -0
  62. data/test/tc_attributes.rb +43 -19
  63. data/test/tc_document.rb +1 -1
  64. data/test/tc_document_write.rb +15 -8
  65. data/test/tc_dtd.rb +36 -20
  66. data/test/tc_encoding.rb +13 -0
  67. data/test/tc_error.rb +136 -0
  68. data/test/tc_node.rb +2 -3
  69. data/test/tc_node_copy.rb +1 -1
  70. data/test/tc_node_edit.rb +6 -0
  71. data/test/tc_ns.rb +18 -0
  72. data/test/tc_parser.rb +113 -228
  73. data/test/tc_parser_context.rb +1 -2
  74. data/test/tc_reader.rb +24 -14
  75. data/test/tc_relaxng.rb +18 -6
  76. data/test/tc_sax_parser.rb +48 -13
  77. data/test/tc_schema.rb +20 -8
  78. data/test/tc_well_formed.rb +2 -1
  79. data/test/tc_xml.rb +212 -0
  80. data/test/tc_xpath.rb +60 -46
  81. data/test/tc_xpointer.rb +7 -11
  82. data/test/test_suite.rb +4 -3
  83. metadata +32 -115
  84. data/doc/rdoc/classes/LibXML.html +0 -241
  85. data/doc/rdoc/classes/LibXML/XML.html +0 -185
  86. data/doc/rdoc/classes/LibXML/XML/Attr.html +0 -1010
  87. data/doc/rdoc/classes/LibXML/XML/Attributes.html +0 -526
  88. data/doc/rdoc/classes/LibXML/XML/Document.html +0 -1489
  89. data/doc/rdoc/classes/LibXML/XML/Dtd.html +0 -213
  90. data/doc/rdoc/classes/LibXML/XML/Error.html +0 -117
  91. data/doc/rdoc/classes/LibXML/XML/HTMLParser.html +0 -348
  92. data/doc/rdoc/classes/LibXML/XML/InputCallbacks.html +0 -160
  93. data/doc/rdoc/classes/LibXML/XML/NS.html +0 -381
  94. data/doc/rdoc/classes/LibXML/XML/Node.html +0 -3396
  95. data/doc/rdoc/classes/LibXML/XML/Node/FailedModify.html +0 -123
  96. data/doc/rdoc/classes/LibXML/XML/Node/Set.html +0 -440
  97. data/doc/rdoc/classes/LibXML/XML/Node/SetNamespace.html +0 -123
  98. data/doc/rdoc/classes/LibXML/XML/Node/UnknownType.html +0 -123
  99. data/doc/rdoc/classes/LibXML/XML/Parser.html +0 -2239
  100. data/doc/rdoc/classes/LibXML/XML/Parser/Context.html +0 -1255
  101. data/doc/rdoc/classes/LibXML/XML/Parser/ParseError.html +0 -123
  102. data/doc/rdoc/classes/LibXML/XML/Reader.html +0 -2264
  103. data/doc/rdoc/classes/LibXML/XML/RelaxNG.html +0 -237
  104. data/doc/rdoc/classes/LibXML/XML/SaxParser.html +0 -415
  105. data/doc/rdoc/classes/LibXML/XML/Schema.html +0 -308
  106. data/doc/rdoc/classes/LibXML/XML/State.html +0 -124
  107. data/doc/rdoc/classes/LibXML/XML/Tree.html +0 -111
  108. data/doc/rdoc/classes/LibXML/XML/XInclude.html +0 -123
  109. data/doc/rdoc/classes/LibXML/XML/XInclude/Error.html +0 -117
  110. data/doc/rdoc/classes/LibXML/XML/XMLParserOptions.html +0 -198
  111. data/doc/rdoc/classes/LibXML/XML/XPath.html +0 -184
  112. data/doc/rdoc/classes/LibXML/XML/XPath/Context.html +0 -404
  113. data/doc/rdoc/classes/LibXML/XML/XPath/InvalidPath.html +0 -172
  114. data/doc/rdoc/classes/LibXML/XML/XPath/Object.html +0 -627
  115. data/doc/rdoc/classes/LibXML/XML/XPointer.html +0 -170
  116. data/doc/rdoc/classes/LibXML/XML/XPointer/Context.html +0 -123
  117. data/doc/rdoc/classes/LibXML/XML/XPointer/Context/InvalidPath.html +0 -117
  118. data/doc/rdoc/classes/LibXML/XML/XPointer/InvalidExpression.html +0 -124
  119. data/doc/rdoc/classes/singleton.html +0 -114
  120. data/doc/rdoc/created.rid +0 -1
  121. data/doc/rdoc/files/CHANGES.html +0 -442
  122. data/doc/rdoc/files/LICENSE.html +0 -133
  123. data/doc/rdoc/files/README.html +0 -388
  124. data/doc/rdoc/files/VERSION.html +0 -107
  125. data/doc/rdoc/files/ext/libxml/cbg_c.html +0 -101
  126. data/doc/rdoc/files/ext/libxml/libxml_c.html +0 -101
  127. data/doc/rdoc/files/ext/libxml/ruby_xml_attr_c.html +0 -101
  128. data/doc/rdoc/files/ext/libxml/ruby_xml_attributes_c.html +0 -101
  129. data/doc/rdoc/files/ext/libxml/ruby_xml_document_c.html +0 -101
  130. data/doc/rdoc/files/ext/libxml/ruby_xml_dtd_c.html +0 -101
  131. data/doc/rdoc/files/ext/libxml/ruby_xml_html_parser_c.html +0 -101
  132. data/doc/rdoc/files/ext/libxml/ruby_xml_input_cbg_c.html +0 -101
  133. data/doc/rdoc/files/ext/libxml/ruby_xml_node_c.html +0 -101
  134. data/doc/rdoc/files/ext/libxml/ruby_xml_node_set_c.html +0 -101
  135. data/doc/rdoc/files/ext/libxml/ruby_xml_ns_c.html +0 -101
  136. data/doc/rdoc/files/ext/libxml/ruby_xml_parser_c.html +0 -101
  137. data/doc/rdoc/files/ext/libxml/ruby_xml_parser_context_c.html +0 -101
  138. data/doc/rdoc/files/ext/libxml/ruby_xml_reader_c.html +0 -101
  139. data/doc/rdoc/files/ext/libxml/ruby_xml_relaxng_c.html +0 -101
  140. data/doc/rdoc/files/ext/libxml/ruby_xml_sax_parser_c.html +0 -101
  141. data/doc/rdoc/files/ext/libxml/ruby_xml_schema_c.html +0 -101
  142. data/doc/rdoc/files/ext/libxml/ruby_xml_state_c.html +0 -101
  143. data/doc/rdoc/files/ext/libxml/ruby_xml_xinclude_c.html +0 -101
  144. data/doc/rdoc/files/ext/libxml/ruby_xml_xpath_c.html +0 -101
  145. data/doc/rdoc/files/ext/libxml/ruby_xml_xpath_context_c.html +0 -101
  146. data/doc/rdoc/files/ext/libxml/ruby_xml_xpath_object_c.html +0 -101
  147. data/doc/rdoc/files/ext/libxml/ruby_xml_xpointer_c.html +0 -101
  148. data/doc/rdoc/files/ext/libxml/ruby_xml_xpointer_context_c.html +0 -101
  149. data/doc/rdoc/files/lib/libxml/attr_rb.html +0 -108
  150. data/doc/rdoc/files/lib/libxml/attributes_rb.html +0 -108
  151. data/doc/rdoc/files/lib/libxml/document_rb.html +0 -108
  152. data/doc/rdoc/files/lib/libxml/node_rb.html +0 -108
  153. data/doc/rdoc/files/lib/libxml/node_set_rb.html +0 -108
  154. data/doc/rdoc/files/lib/libxml/parser_options_rb.html +0 -107
  155. data/doc/rdoc/files/lib/libxml/parser_rb.html +0 -101
  156. data/doc/rdoc/files/lib/libxml/properties_rb.html +0 -108
  157. data/doc/rdoc/files/lib/libxml/tree_rb.html +0 -107
  158. data/doc/rdoc/files/lib/libxml_rb.html +0 -124
  159. data/doc/rdoc/files/lib/xml/libxml_rb.html +0 -124
  160. data/doc/rdoc/files/lib/xml_rb.html +0 -134
  161. data/doc/rdoc/fr_class_index.html +0 -62
  162. data/doc/rdoc/fr_file_index.html +0 -66
  163. data/doc/rdoc/fr_method_index.html +0 -392
  164. data/doc/rdoc/index.html +0 -24
  165. data/doc/rdoc/rdoc-style.css +0 -208
  166. data/ext/libxml/ruby_xml_node_set.c +0 -172
  167. data/ext/libxml/ruby_xml_node_set.h +0 -20
  168. data/ext/libxml/ruby_xml_xpointer_context.c +0 -22
  169. data/ext/libxml/ruby_xml_xpointer_context.h +0 -18
  170. data/lib/libxml/node_set.rb +0 -27
  171. data/lib/libxml2-2.dll +0 -0
  172. data/lib/libxml_ruby.dll.a +0 -0
  173. data/lib/libxml_ruby.so +0 -0
  174. data/test/tc_node_set.rb +0 -24
  175. data/test/tc_node_set2.rb +0 -37
@@ -5,7 +5,7 @@
5
5
  /*
6
6
  * Document-class: LibXML::XML::Attributes
7
7
  *
8
- * Provides access to an elements attributes (XML::Attr).
8
+ * Provides access to an element's attributes (XML::Attr).
9
9
  *
10
10
  * Basic Usage:
11
11
  * require 'xml'
@@ -1,1135 +1,1144 @@
1
- /* $Id: ruby_xml_document.c 502 2008-07-22 01:45:31Z cfis $ */
2
-
3
- /* Please see the LICENSE file for copyright and distribution information */
4
-
5
- /*
6
- * Document-class: LibXML::XML::Document
7
- *
8
- * Reads or writes an XML document:
9
- *
10
- * Reading:
11
- * require 'xml'
12
- *
13
- * doc = XML::Document.new()
14
- * doc.root = XML::Node.new('root_node')
15
- * doc.root << XML::Node.new('elem1')
16
- * doc.save('output.xml', format)
17
- *
18
- * Writing:
19
- * require 'libxml'
20
- * doc = XML::Document.file('output.xml')
21
- * root = doc.root
22
- */
23
-
24
- #include <stdarg.h>
25
- #include "ruby_libxml.h"
26
- #include "ruby_xml_document.h"
27
-
28
-
29
- VALUE cXMLDocument;
30
-
31
- /*
32
- * call-seq:
33
- * document.compression -> num
34
- *
35
- * Obtain this document's compression mode identifier.
36
- */
37
- VALUE
38
- ruby_xml_document_compression_get(VALUE self) {
39
- #ifdef HAVE_ZLIB_H
40
- ruby_xml_document_t *rxd;
41
- int compmode;
42
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
43
-
44
- compmode = xmlGetDocCompressMode(rxd->doc);
45
- if (compmode == -1)
46
- return(Qnil);
47
- else
48
- return(INT2NUM(compmode));
49
- #else
50
- rb_warn("libxml not compiled with zlib support");
51
- return(Qfalse);
52
- #endif
53
- }
54
-
55
-
56
- /*
57
- * call-seq:
58
- * document.compression = num
59
- *
60
- * Set this document's compression mode.
61
- */
62
- VALUE
63
- ruby_xml_document_compression_set(VALUE self, VALUE num) {
64
- #ifdef HAVE_ZLIB_H
65
- ruby_xml_document_t *rxd;
66
- int compmode;
67
- Check_Type(num, T_FIXNUM);
68
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
69
-
70
- if (rxd->doc == NULL) {
71
- return(Qnil);
72
- } else {
73
- xmlSetDocCompressMode(rxd->doc, NUM2INT(num));
74
-
75
- compmode = xmlGetDocCompressMode(rxd->doc);
76
- if (compmode == -1)
77
- return(Qnil);
78
- else
79
- return(INT2NUM(compmode));
80
- }
81
- #else
82
- rb_warn("libxml compiled without zlib support");
83
- return(Qfalse);
84
- #endif
85
- }
86
-
87
-
88
- /*
89
- * call-seq:
90
- * document.compression? -> (true|false)
91
- *
92
- * Determine whether this document is compressed.
93
- */
94
- VALUE
95
- ruby_xml_document_compression_q(VALUE self) {
96
- #ifdef HAVE_ZLIB_H
97
- ruby_xml_document_t *rxd;
98
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
99
-
100
- if (rxd->doc->compression != -1)
101
- return(Qtrue);
102
- else
103
- return(Qfalse);
104
- #else
105
- rb_warn("libxml compiled without zlib support");
106
- return(Qfalse);
107
- #endif
108
- }
109
-
110
-
111
- /*
112
- * call-seq:
113
- * document.child -> node
114
- *
115
- * Get this document's child node.
116
- */
117
- VALUE
118
- ruby_xml_document_child_get(VALUE self) {
119
- ruby_xml_document_t *rxd;
120
-
121
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
122
-
123
- if (rxd->doc->children == NULL)
124
- return(Qnil);
125
-
126
- return ruby_xml_node2_wrap(cXMLNode, rxd->doc->children);
127
- }
128
-
129
-
130
- /*
131
- * call-seq:
132
- * document.child? -> (true|false)
133
- *
134
- * Determine whether this document has a child node.
135
- */
136
- VALUE
137
- ruby_xml_document_child_q(VALUE self) {
138
- ruby_xml_document_t *rxd;
139
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
140
-
141
- if (rxd->doc->children == NULL)
142
- return(Qfalse);
143
- else
144
- return(Qtrue);
145
- }
146
-
147
-
148
- /*
149
- * call-seq:
150
- * document.dump([stream]) -> true
151
- *
152
- * Dump this document's XML to the specified IO stream.
153
- * If no stream is specified, stdout is used.
154
- */
155
- VALUE
156
- ruby_xml_document_dump(int argc, VALUE *argv, VALUE self) {
157
- OpenFile *fptr;
158
- VALUE io;
159
- FILE *out;
160
- ruby_xml_document_t *rxd;
161
-
162
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
163
- if (rxd->doc == NULL)
164
- return(Qnil);
165
-
166
- switch (argc) {
167
- case 0:
168
- io = rb_stdout;
169
- break;
170
- case 1:
171
- io = argv[0];
172
- if (!rb_obj_is_kind_of(io, rb_cIO))
173
- rb_raise(rb_eTypeError, "need an IO object");
174
- break;
175
- default:
176
- rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
177
- }
178
-
179
- GetOpenFile(io, fptr);
180
- rb_io_check_writable(fptr);
181
- out = GetWriteFile(fptr);
182
- xmlDocDump(out, rxd->doc);
183
- return(Qtrue);
184
- }
185
-
186
-
187
- /*
188
- * call-seq:
189
- * document.debug_dump([stream]) -> true
190
- *
191
- * Debug version of dump.
192
- */
193
- VALUE
194
- ruby_xml_document_debug_dump(int argc, VALUE *argv, VALUE self) {
195
- #ifdef LIBXML_DEBUG_ENABLED
196
- OpenFile *fptr;
197
- VALUE io;
198
- FILE *out;
199
- ruby_xml_document_t *rxd;
200
-
201
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
202
- if (rxd->doc == NULL)
203
- return(Qnil);
204
-
205
- switch (argc) {
206
- case 0:
207
- io = rb_stderr;
208
- break;
209
- case 1:
210
- io = argv[0];
211
- if (!rb_obj_is_kind_of(io, rb_cIO))
212
- rb_raise(rb_eTypeError, "need an IO object");
213
- break;
214
- default:
215
- rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
216
- }
217
-
218
- GetOpenFile(io, fptr);
219
- rb_io_check_writable(fptr);
220
- out = GetWriteFile(fptr);
221
- xmlDebugDumpDocument(out, rxd->doc);
222
- return(Qtrue);
223
- #else
224
- rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
225
- return(Qfalse);
226
- #endif
227
- }
228
-
229
-
230
- /*
231
- * call-seq:
232
- * document.debug_dump_head([stream]) -> true
233
- *
234
- * Debug-dump this document's header to the specified IO stream.
235
- * If no stream is specified, stdout is used.
236
- */
237
- VALUE
238
- ruby_xml_document_debug_dump_head(int argc, VALUE *argv, VALUE self) {
239
- #ifdef LIBXML_DEBUG_ENABLED
240
- OpenFile *fptr;
241
- VALUE io;
242
- FILE *out;
243
- ruby_xml_document_t *rxd;
244
-
245
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
246
- if (rxd->doc == NULL)
247
- return(Qnil);
248
-
249
- switch (argc) {
250
- case 0:
251
- io = rb_stdout;
252
- break;
253
- case 1:
254
- io = argv[0];
255
- if (!rb_obj_is_kind_of(io, rb_cIO))
256
- rb_raise(rb_eTypeError, "need an IO object");
257
- break;
258
- default:
259
- rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
260
- }
261
-
262
- GetOpenFile(io, fptr);
263
- rb_io_check_writable(fptr);
264
- out = GetWriteFile(fptr);
265
- xmlDebugDumpDocumentHead(out, rxd->doc);
266
- return(Qtrue);
267
- #else
268
- rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
269
- return(Qfalse);
270
- #endif
271
- }
272
-
273
-
274
- /*
275
- * call-seq:
276
- * document.format_dump([stream], [spacing]) -> true
277
- *
278
- * Dump this document's formatted XML to the specified IO stream.
279
- * If no stream is specified, stdout is used. If spacing is
280
- * specified, it must be a boolean that determines whether
281
- * spacing is used.
282
- */
283
- VALUE
284
- ruby_xml_document_format_dump(int argc, VALUE *argv, VALUE self) {
285
- OpenFile *fptr;
286
- VALUE bool, io;
287
- FILE *out;
288
- ruby_xml_document_t *rxd;
289
- int size, spacing;
290
-
291
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
292
- if (rxd->doc == NULL)
293
- return(Qnil);
294
-
295
- switch (argc) {
296
- case 0:
297
- io = rb_stdout;
298
- spacing = 1;
299
- break;
300
- case 1:
301
- io = argv[0];
302
- if (!rb_obj_is_kind_of(io, rb_cIO))
303
- rb_raise(rb_eTypeError, "need an IO object");
304
- spacing = 1;
305
- break;
306
- case 2:
307
- io = argv[0];
308
- if (!rb_obj_is_kind_of(io, rb_cIO))
309
- rb_raise(rb_eTypeError, "need an IO object");
310
- bool = argv[1];
311
- if (TYPE(bool) == T_TRUE)
312
- spacing = 1;
313
- else if (TYPE(bool) == T_FALSE)
314
- spacing = 0;
315
- else
316
- rb_raise(rb_eTypeError, "incorect argument type, second argument must be bool");
317
-
318
- break;
319
- default:
320
- rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
321
- }
322
-
323
- GetOpenFile(io, fptr);
324
- rb_io_check_writable(fptr);
325
- out = GetWriteFile(fptr);
326
- size = xmlDocFormatDump(out, rxd->doc, spacing);
327
- return(INT2NUM(size));
328
- }
329
-
330
-
331
- /*
332
- * call-seq:
333
- * document.debug_format_dump([stream]) -> true
334
- *
335
- * *Deprecated* in favour of format_dump.
336
- */
337
- VALUE
338
- ruby_xml_document_debug_format_dump(int argc, VALUE *argv, VALUE self) {
339
- rb_warn("debug_format_dump has been deprecaited, use format_dump instead");
340
- return(ruby_xml_document_format_dump(argc, argv, self));
341
- }
342
-
343
-
344
- /*
345
- * call-seq:
346
- * document.encoding -> "encoding"
347
- *
348
- * Obtain the encoding specified by this document.
349
- */
350
- VALUE
351
- ruby_xml_document_encoding_get(VALUE self) {
352
- ruby_xml_document_t *rxd;
353
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
354
- if (rxd->doc->encoding == NULL)
355
- return(Qnil);
356
- else
357
- return(rb_str_new2((const char*)rxd->doc->encoding));
358
- }
359
-
360
-
361
- /*
362
- * call-seq:
363
- * document.encoding = "encoding"
364
- *
365
- * Set the encoding for this document.
366
- */
367
- VALUE
368
- ruby_xml_document_encoding_set(VALUE self, VALUE encoding) {
369
- ruby_xml_document_t *rxd;
370
-
371
- Check_Type(encoding, T_STRING);
372
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
373
- rxd->doc->encoding = xmlStrdup(StringValuePtr(encoding));
374
- return(ruby_xml_document_encoding_get(self));
375
- }
376
-
377
-
378
- /*
379
- * call-seq:
380
- * document.filename -> "filename"
381
- *
382
- * Obtain the filename this document was read from.
383
- */
384
- VALUE
385
- ruby_xml_document_filename_get(VALUE self) {
386
- ruby_xml_document_t *rxd;
387
- rx_file_data *data;
388
-
389
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
390
- if (rxd->data == NULL)
391
- return(Qnil);
392
-
393
- switch (rxd->data_type) {
394
- case RUBY_LIBXML_SRC_TYPE_NULL:
395
- return(Qnil);
396
- case RUBY_LIBXML_SRC_TYPE_FILE:
397
- data = (rx_file_data *)rxd->data;
398
- return(data->filename);
399
- default:
400
- rb_fatal("Unknown document type in libxml");
401
- }
402
-
403
- return(Qnil);
404
- }
405
-
406
-
407
- void
408
- ruby_xml_document_free(ruby_xml_document_t *rxd) {
409
- void *data;
410
-
411
- if (rxd->doc == NULL) return;
412
- rxd->doc->_private=NULL;
413
- #ifdef NODE_DEBUG
414
- fprintf(stderr,"ruby_xml_document_free 0x%x/0x%x\n",rxd,rxd->doc);
415
- #endif
416
- xmlFreeDoc(rxd->doc);
417
- rxd->doc = NULL;
418
-
419
- switch(rxd->data_type) {
420
- case RUBY_LIBXML_SRC_TYPE_NULL:
421
- break;
422
- case RUBY_LIBXML_SRC_TYPE_FILE:
423
- data = (void*)(rx_file_data *)rxd->data;
424
- ruby_xfree((rx_file_data *)data);
425
- break;
426
- case RUBY_LIBXML_SRC_TYPE_STRING:
427
- data = (void*)(rx_string_data *)rxd->data;
428
- ruby_xfree((rx_string_data *)data);
429
- break;
430
- case RUBY_LIBXML_SRC_TYPE_IO:
431
- data = (void*)(rx_io_data *)rxd->data;
432
- ruby_xfree((rx_io_data *)data);
433
- break;
434
- default:
435
- rb_fatal("Unknown data type, %d", rxd->data_type);
436
- }
437
-
438
- ruby_xfree(rxd);
439
- }
440
-
441
- void
442
- ruby_xml_document_mark(ruby_xml_document_t *rxd) {
443
- // will mark parsers and source types
444
- // I do not thing doc->parent has anything useful in it.
445
- rb_gc_mark(LIBXML_STATE);
446
- }
447
-
448
- /*
449
- * call-seq:
450
- * XML::Document.new(xml_version = 1.0) -> document
451
- *
452
- * Create a new XML::Document, optionally specifying the
453
- * XML version.
454
- */
455
- VALUE
456
- ruby_xml_document_new(int argc, VALUE *argv, VALUE class) {
457
- VALUE docobj, xmlver;
458
-
459
- switch (argc) {
460
- case 0:
461
- xmlver = rb_str_new2("1.0");
462
- break;
463
- case 1:
464
- rb_scan_args(argc, argv, "01", &xmlver);
465
- break;
466
- default:
467
- rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
468
- }
469
-
470
- docobj = ruby_xml_document_new_native(cXMLDocument, xmlver);
471
- return(docobj);
472
- }
473
-
474
-
475
- /*
476
- * call-seq:
477
- * document.last -> node
478
- *
479
- * Obtain the last node.
480
- */
481
- VALUE
482
- ruby_xml_document_last_get(VALUE self) {
483
- ruby_xml_document_t *rxd;
484
-
485
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
486
-
487
- if (rxd->doc->last == NULL)
488
- return(Qnil);
489
-
490
- return ruby_xml_node2_wrap(cXMLNode, rxd->doc->last);
491
- }
492
-
493
-
494
- /*
495
- * call-seq:
496
- * document.last? -> (true|false)
497
- *
498
- * Determine whether there is a last node.
499
- */
500
- VALUE
501
- ruby_xml_document_last_q(VALUE self) {
502
- ruby_xml_document_t *rxd;
503
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
504
-
505
- if (rxd->doc->last == NULL)
506
- return(Qfalse);
507
- else
508
- return(Qtrue);
509
- }
510
-
511
- VALUE
512
- ruby_xml_document_wrap(xmlDocPtr xdoc) {
513
- VALUE obj;
514
- ruby_xml_document_t *rx;
515
-
516
- // This node is already wrapped
517
- if (xdoc->_private != NULL)
518
- return (VALUE)xdoc->_private;
519
-
520
- obj=Data_Make_Struct(cXMLDocument, ruby_xml_document_t,
521
- ruby_xml_document_mark, ruby_xml_document_free,rx);
522
-
523
- rx->doc=xdoc;
524
- xdoc->_private=(void*)obj;
525
- rx->data = NULL;
526
- rx->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
527
-
528
- #ifdef NODE_DEBUG
529
- fprintf(stderr,"wrap rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)xnode,(long)obj);
530
- #endif
531
- return obj;
532
- }
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(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.root -> node
677
- *
678
- * Obtain the root node.
679
- */
680
- VALUE
681
- ruby_xml_document_root_get(VALUE self) {
682
- ruby_xml_document_t *rxd;
683
- xmlNodePtr root;
684
-
685
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
686
- root = xmlDocGetRootElement(rxd->doc);
687
-
688
- if (root == NULL)
689
- return(Qnil);
690
-
691
- return ruby_xml_node2_wrap(cXMLNode, root);
692
- }
693
-
694
-
695
- /*
696
- * call-seq:
697
- * document.root = node
698
- *
699
- * Set the root node.
700
- */
701
- VALUE
702
- ruby_xml_document_root_set(VALUE self, VALUE node) {
703
- ruby_xml_document_t *rxd;
704
- xmlNodePtr xroot, xnode;
705
-
706
- if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
707
- rb_raise(rb_eTypeError, "must pass an XML::Node type object");
708
-
709
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
710
- Data_Get_Struct(node, xmlNode, xnode);
711
- xroot = xmlDocSetRootElement(rxd->doc, xnode);
712
- if (xroot == NULL)
713
- return(Qnil);
714
-
715
- return ruby_xml_node2_wrap(cXMLNode, xroot);
716
- }
717
-
718
-
719
- /*
720
- * call-seq:
721
- * document.save(filename, format = false) -> int
722
- *
723
- * Save this document to the file given by filename,
724
- * optionally formatting the output.
725
-
726
- * Parameters:
727
- * filename: The filename or URL of the new document
728
- * format: Specifies whether formatting spaces should be added.
729
- * returns: The number of bytes written or -1 in case of error.
730
- */
731
- VALUE
732
- ruby_xml_document_save(int argc, VALUE *argv, VALUE self) {
733
- ruby_xml_document_t *rxd;
734
- const char *filename;
735
- int format = 0;
736
- int len;
737
-
738
- if (argc <1 || argc > 2)
739
- rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
740
-
741
- Check_Type(argv[0], T_STRING);
742
- filename = StringValuePtr(argv[0]);
743
-
744
- if (argc == 2)
745
- {
746
- switch (TYPE(argv[1])) {
747
- case T_TRUE:
748
- format = 1;
749
- break;
750
- case T_FALSE:
751
- format = 0;
752
- break;
753
- default:
754
- rb_raise(rb_eArgError, "The second parameter (format) must be true or false");
755
- }
756
- }
757
-
758
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
759
- len = xmlSaveFormatFileEnc(filename, rxd->doc, (const char*)rxd->doc->encoding, format);
760
-
761
- if (len == -1)
762
- rb_raise(rb_eIOError, "Could not write document");
763
- else
764
- return(INT2NUM(len));
765
- }
766
-
767
-
768
- /*
769
- * call-seq:
770
- * document.standalone? -> (true|false)
771
- *
772
- * Determine whether this is a standalone document.
773
- */
774
- VALUE
775
- ruby_xml_document_standalone_q(VALUE self) {
776
- ruby_xml_document_t *rxd;
777
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
778
- if (rxd->doc->standalone)
779
- return(Qtrue);
780
- else
781
- return(Qfalse);
782
- }
783
-
784
-
785
- /*
786
- * call-seq:
787
- * document.to_s({format=true,encoding) -> "xml"
788
- *
789
- * Coerce this document to a string representation
790
- * of it's XML. The default is to pretty format, but this
791
- * depends Parser#indent_tree_output==true or
792
- * Parser#default_keep_blanks==false.
793
- *
794
- * The encoding is not applied to the document, but is
795
- * encoding target of the resulting string.
796
- */
797
- VALUE
798
- ruby_xml_document_to_s(int argc, VALUE *argv, VALUE self) {
799
- ruby_xml_document_t *rxd;
800
- xmlChar *result, *encoding=NULL;
801
- int format, len;
802
- VALUE rresult;
803
-
804
- switch (argc) {
805
- case 0:
806
- format = 1;
807
- break;
808
- case 2:
809
- if (TYPE(argv[1]) == T_STRING)
810
- encoding=(xmlChar *)StringValuePtr(argv[1]);
811
- case 1:
812
- if (TYPE(argv[0]) == T_TRUE)
813
- format = 1;
814
- else if (TYPE(argv[0]) == T_FALSE)
815
- format = 0;
816
- else
817
- rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
818
- break;
819
- default:
820
- rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
821
- }
822
-
823
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
824
- if (rxd->doc == NULL) {
825
- return(Qnil);
826
- } else if (encoding != NULL) {
827
- if (format) {
828
- xmlDocDumpFormatMemoryEnc(rxd->doc, &result, &len,
829
- (const char*)encoding, format);
830
- } else {
831
- xmlDocDumpMemoryEnc(rxd->doc, &result, &len,
832
- (const char *)encoding);
833
- }
834
- } else {
835
- if (format)
836
- xmlDocDumpFormatMemory(rxd->doc, &result, &len, format);
837
- else
838
- xmlDocDumpMemory(rxd->doc, &result, &len);
839
- }
840
- rresult=rb_str_new((const char*)result,len);
841
- xmlFree(result);
842
- return rresult;
843
- }
844
-
845
-
846
- /*
847
- * call-seq:
848
- * document.url -> "url"
849
- *
850
- * Obtain this document's source URL, if any.
851
- */
852
- VALUE
853
- ruby_xml_document_url_get(VALUE self) {
854
- ruby_xml_document_t *rxd;
855
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
856
- if (rxd->doc->URL == NULL)
857
- return(Qnil);
858
- else
859
- return(rb_str_new2((const char*)rxd->doc->URL));
860
- }
861
-
862
-
863
- /*
864
- * call-seq:
865
- * document.version -> "version"
866
- *
867
- * Obtain the XML version specified by this document.
868
- */
869
- VALUE
870
- ruby_xml_document_version_get(VALUE self) {
871
- ruby_xml_document_t *rxd;
872
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
873
- if (rxd->doc->version == NULL)
874
- return(Qnil);
875
- else
876
- return(rb_str_new2((const char*)rxd->doc->version));
877
- }
878
-
879
-
880
- /*
881
- * call-seq:
882
- * document.xinclude -> num
883
- *
884
- * Process xinclude directives in this document.
885
- */
886
- VALUE
887
- ruby_xml_document_xinclude(VALUE self) {
888
- #ifdef LIBXML_XINCLUDE_ENABLED
889
- ruby_xml_document_t *rxd;
890
- int ret;
891
-
892
- Data_Get_Struct(self, ruby_xml_document_t, rxd);
893
- ret = xmlXIncludeProcess(rxd->doc);
894
- if (ret >= 0)
895
- return(INT2NUM(ret));
896
- else
897
- rb_raise(eXMLXIncludeError, "error processing xinclude directives in document");
898
- #else
899
- rb_warn("libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
900
- return(Qfalse);
901
- #endif
902
- }
903
-
904
- void
905
- LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
906
- {
907
- if (rb_block_given_p()) {
908
- char buff[1024];
909
- snprintf(buff, 1024, msg, ap);
910
- rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
911
- } else {
912
- fprintf(stderr, "error -- found validity error: ");
913
- fprintf(stderr, msg, ap);
914
- }
915
- }
916
-
917
- void
918
- LibXML_validity_warning(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), Qfalse));
924
- } else {
925
- fprintf(stderr, "warning -- found validity error: ");
926
- fprintf(stderr, msg, ap);
927
- }
928
- }
929
-
930
- /*
931
- * call-seq:
932
- * document.validate_schema(schema) -> (true|false)
933
- *
934
- * Validate this document against the specified XML::Schema.
935
- *
936
- * If a block is provided it is used as an error handler for validaten errors.
937
- * The block is called with two argument, the message and a flag indication
938
- * if the message is an error (true) or a warning (false).
939
- */
940
- VALUE
941
- ruby_xml_document_validate_schema(VALUE self, VALUE schema) {
942
- xmlSchemaValidCtxtPtr vptr;
943
- ruby_xml_document_t *c_doc;
944
- ruby_xml_schema *c_schema;
945
- int is_invalid;
946
-
947
- Data_Get_Struct(self, ruby_xml_document_t, c_doc);
948
- Data_Get_Struct(schema, ruby_xml_schema, c_schema);
949
-
950
- vptr = xmlSchemaNewValidCtxt(c_schema->schema);
951
-
952
- xmlSchemaSetValidErrors(vptr, (xmlSchemaValidityErrorFunc)LibXML_validity_error,
953
- (xmlSchemaValidityWarningFunc)LibXML_validity_warning, NULL);
954
-
955
- is_invalid = xmlSchemaValidateDoc(vptr, c_doc->doc);
956
- xmlSchemaFreeValidCtxt(vptr);
957
- if (is_invalid) {
958
- return Qfalse;
959
- } else {
960
- return Qtrue;
961
- }
962
- }
963
-
964
- /*
965
- * call-seq:
966
- * document.validate_schema(relaxng) -> (true|false)
967
- *
968
- * Validate this document against the specified XML::RelaxNG.
969
- *
970
- * If a block is provided it is used as an error handler for validaten errors.
971
- * The block is called with two argument, the message and a flag indication
972
- * if the message is an error (true) or a warning (false).
973
- */
974
- VALUE
975
- ruby_xml_document_validate_relaxng(VALUE self, VALUE relaxng) {
976
- xmlRelaxNGValidCtxtPtr vptr;
977
- ruby_xml_document_t *c_doc;
978
- ruby_xml_relaxng *c_relaxng;
979
- int is_invalid;
980
-
981
- Data_Get_Struct(self, ruby_xml_document_t, c_doc);
982
- Data_Get_Struct(relaxng, ruby_xml_relaxng, c_relaxng);
983
-
984
- vptr = xmlRelaxNGNewValidCtxt(c_relaxng->relaxng);
985
-
986
- xmlRelaxNGSetValidErrors(vptr, (xmlRelaxNGValidityErrorFunc)LibXML_validity_error,
987
- (xmlRelaxNGValidityWarningFunc)LibXML_validity_warning, NULL);
988
-
989
- is_invalid = xmlRelaxNGValidateDoc(vptr, c_doc->doc);
990
- xmlRelaxNGFreeValidCtxt(vptr);
991
- if (is_invalid) {
992
- return Qfalse;
993
- } else {
994
- return Qtrue;
995
- }
996
- }
997
-
998
-
999
- /*
1000
- * call-seq:
1001
- * document.validate(dtd) -> (true|false)
1002
- *
1003
- * Validate this document against the specified XML::DTD.
1004
- */
1005
- VALUE
1006
- ruby_xml_document_validate_dtd(VALUE self, VALUE dtd) {
1007
- xmlValidCtxt cvp;
1008
- ruby_xml_document_t *c_doc;
1009
- ruby_xml_dtd *c_dtd;
1010
-
1011
- Data_Get_Struct(self, ruby_xml_document_t, c_doc);
1012
- Data_Get_Struct(dtd, ruby_xml_dtd, c_dtd);
1013
-
1014
- cvp.userData = NULL;
1015
- cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
1016
- cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
1017
-
1018
- cvp.nodeNr = 0;
1019
- cvp.nodeTab = NULL;
1020
- cvp.vstateNr = 0;
1021
- cvp.vstateTab = NULL;
1022
-
1023
- if ( xmlValidateDtd(&cvp, c_doc->doc, c_dtd->dtd) )
1024
- return(Qtrue);
1025
- else
1026
- return(Qfalse);
1027
-
1028
- // int xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd)
1029
- /*
1030
- int
1031
- validate(self, ...)
1032
- xmlDocPtr self
1033
- PREINIT:
1034
- xmlValidCtxt cvp;
1035
- xmlDtdPtr dtd;
1036
- SV * dtd_sv;
1037
- STRLEN n_a, len;
1038
- CODE:
1039
- LibXML_init_error();
1040
- cvp.userData = (void*)PerlIO_stderr();
1041
- cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
1042
- cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
1043
- // we need to initialize the node stack, because perl might
1044
- // already messed it up.
1045
- //
1046
- cvp.nodeNr = 0;
1047
- cvp.nodeTab = NULL;
1048
- cvp.vstateNr = 0;
1049
- cvp.vstateTab = NULL;
1050
-
1051
- if (items > 1) {
1052
- dtd_sv = ST(1);
1053
- if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
1054
- dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
1055
- }
1056
- else {
1057
- croak("is_valid: argument must be a DTD object");
1058
- }
1059
- RETVAL = xmlValidateDtd(&cvp, self , dtd);
1060
- }
1061
- else {
1062
- RETVAL = xmlValidateDocument(&cvp, self);
1063
- }
1064
- sv_2mortal(LibXML_error);
1065
-
1066
- if (RETVAL == 0) {
1067
- LibXML_croak_error();
1068
- }
1069
- OUTPUT:
1070
- RETVAL
1071
- */
1072
- }
1073
-
1074
- /*
1075
- * call-seq:
1076
- * document.reader -> reader
1077
- *
1078
- * Create a XML::Reader from the document. This is a shortcut to
1079
- * XML::Reader.walker().
1080
- */
1081
- static VALUE
1082
- ruby_xml_document_reader(VALUE self)
1083
- {
1084
- return ruby_xml_reader_new_walker(cXMLReader, self);
1085
- }
1086
-
1087
- // Rdoc needs to know
1088
- #ifdef RDOC_NEVER_DEFINED
1089
- mLibXML = rb_define_module("LibXML");
1090
- mXML = rb_define_module_under(mLibXML, "XML");
1091
- #endif
1092
-
1093
- void
1094
- ruby_init_xml_document(void) {
1095
- cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
1096
- rb_define_singleton_method(cXMLDocument, "file", ruby_xml_document_new_file, 1);
1097
- rb_define_singleton_method(cXMLDocument, "new", ruby_xml_document_new, -1);
1098
-
1099
- //rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
1100
- //eDTDValidityWarning = rb_define_class_under(cXMLNode, "ValidityWarning", eXMLError);
1101
- //eDTDValidityError = rb_define_class_under(cXMLNode, "ValidityWarning", eXMLError);
1102
- rb_define_method(cXMLDocument, "child", ruby_xml_document_child_get, 0);
1103
- rb_define_method(cXMLDocument, "child?", ruby_xml_document_child_q, 0);
1104
- rb_define_method(cXMLDocument, "compression", ruby_xml_document_compression_get, 0);
1105
- rb_define_method(cXMLDocument, "compression=", ruby_xml_document_compression_set, 1);
1106
- rb_define_method(cXMLDocument, "compression?", ruby_xml_document_compression_q, 0);
1107
- rb_define_method(cXMLDocument, "dump", ruby_xml_document_dump, -1);
1108
- rb_define_method(cXMLDocument, "debug_dump", ruby_xml_document_debug_dump, -1);
1109
- rb_define_method(cXMLDocument, "debug_dump_head", ruby_xml_document_debug_dump_head, -1);
1110
- rb_define_method(cXMLDocument, "debug_format_dump", ruby_xml_document_debug_format_dump, -1);
1111
- rb_define_method(cXMLDocument, "encoding", ruby_xml_document_encoding_get, 0);
1112
- rb_define_method(cXMLDocument, "encoding=", ruby_xml_document_encoding_set, 1);
1113
- rb_define_method(cXMLDocument, "filename", ruby_xml_document_filename_get, 0);
1114
- rb_define_method(cXMLDocument, "format_dump", ruby_xml_document_format_dump, -1);
1115
- rb_define_method(cXMLDocument, "last", ruby_xml_document_last_get, 0);
1116
- rb_define_method(cXMLDocument, "last?", ruby_xml_document_last_q, 0);
1117
- rb_define_method(cXMLDocument, "next", ruby_xml_document_next_get, 0);
1118
- rb_define_method(cXMLDocument, "next?", ruby_xml_document_next_q, 0);
1119
- rb_define_method(cXMLDocument, "parent", ruby_xml_document_parent_get, 0);
1120
- rb_define_method(cXMLDocument, "parent?", ruby_xml_document_parent_q, 0);
1121
- rb_define_method(cXMLDocument, "prev", ruby_xml_document_prev_get, 0);
1122
- rb_define_method(cXMLDocument, "prev?", ruby_xml_document_prev_q, 0);
1123
- rb_define_method(cXMLDocument, "root", ruby_xml_document_root_get, 0);
1124
- rb_define_method(cXMLDocument, "root=", ruby_xml_document_root_set, 1);
1125
- rb_define_method(cXMLDocument, "save", ruby_xml_document_save, -1);
1126
- rb_define_method(cXMLDocument, "standalone?", ruby_xml_document_standalone_q, 0);
1127
- rb_define_method(cXMLDocument, "to_s", ruby_xml_document_to_s, -1);
1128
- rb_define_method(cXMLDocument, "url", ruby_xml_document_url_get, 0);
1129
- rb_define_method(cXMLDocument, "version", ruby_xml_document_version_get, 0);
1130
- rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
1131
- rb_define_method(cXMLDocument, "validate", ruby_xml_document_validate_dtd, 1);
1132
- rb_define_method(cXMLDocument, "validate_schema", ruby_xml_document_validate_schema, 1);
1133
- rb_define_method(cXMLDocument, "validate_relaxng", ruby_xml_document_validate_relaxng, 1);
1134
- rb_define_method(cXMLDocument, "reader", ruby_xml_document_reader, 0);
1135
- }
1
+ /* $Id: ruby_xml_document.c 575 2008-11-18 09:22:15Z cfis $ */
2
+
3
+ /*
4
+ * Document-class: LibXML::XML::Document
5
+ *
6
+ * The XML::Document class provides a tree based API for working
7
+ * with xml documents. You may directly create a document and
8
+ * manipulate it, or create a document from a data source by
9
+ * using an XML::Parser object.
10
+ *
11
+ * To create a document from scratch:
12
+ *
13
+ * doc = XML::Document.new()
14
+ * doc.root = XML::Node.new('root_node')
15
+ * doc.root << XML::Node.new('elem1')
16
+ * doc.save('output.xml', format)
17
+ *
18
+ * To read a document
19
+ *
20
+ * doc = XML::Document.file('my_file')
21
+ *
22
+ * To use a parser to read a document:
23
+ *
24
+ * parser = XML::Parser.new
25
+ * parser.file = 'my_file'
26
+ * doc = parser.parse
27
+ */
28
+
29
+ #include <stdarg.h>
30
+ #include <st.h>
31
+ #include "ruby_libxml.h"
32
+ #include "ruby_xml_document.h"
33
+
34
+
35
+ VALUE cXMLDocument;
36
+
37
+
38
+ /* We have to make sure that documents are freed after
39
+ XPathObjects. The Ruby gc does not guarantee this
40
+ at shutdown or in normal operation when a document,
41
+ xpath context and xpath object form a cycle. So
42
+ we implement this simple reference counting scheme.
43
+ It works as you'd expect, except with a simple twist.
44
+ If a document is freed, but still has outstanding
45
+ references, its reference count is made negative. Thus
46
+ if it has ref_count of 1, then its becomes -1. At that
47
+ point, decrement will increase the account to 0, and
48
+ once it reaches 0, the document is freed. */
49
+
50
+ static st_table *ref_count_table = 0;
51
+
52
+ void
53
+ ruby_xml_document_internal_free(xmlDocPtr xdoc) {
54
+ st_delete(ref_count_table, (st_data_t*)&xdoc, 0);
55
+ xdoc->_private = NULL;
56
+ xmlFreeDoc(xdoc);
57
+ }
58
+
59
+ int
60
+ ruby_xml_document_incr(xmlDocPtr xdoc) {
61
+ int ref_count;
62
+
63
+ if (st_lookup(ref_count_table, (st_data_t)xdoc, (st_data_t*)&ref_count))
64
+ {
65
+ ref_count++;
66
+ st_insert(ref_count_table, (st_data_t)xdoc, (st_data_t)ref_count);
67
+ }
68
+ else
69
+ {
70
+ ref_count = 1;
71
+ st_add_direct(ref_count_table, (st_data_t)xdoc, (st_data_t)ref_count);
72
+ }
73
+
74
+ return ref_count;
75
+ }
76
+
77
+ int
78
+ ruby_xml_document_decr(xmlDocPtr xdoc) {
79
+ int ref_count = 0;
80
+
81
+ if (!st_lookup(ref_count_table, (st_data_t)xdoc, (st_data_t*)&ref_count))
82
+ rb_raise(rb_eRuntimeError, "Document does not have a reference count.");
83
+
84
+ if (ref_count == 0)
85
+ {
86
+ rb_raise(rb_eRuntimeError, "Document already has no references.");
87
+ }
88
+ else if (ref_count > 0)
89
+ {
90
+ ref_count--;
91
+ }
92
+ else
93
+ {
94
+ ref_count++;
95
+ if (ref_count == 0)
96
+ {
97
+ ruby_xml_document_internal_free(xdoc);
98
+ return ref_count;
99
+ }
100
+ }
101
+
102
+ st_insert(ref_count_table, (st_data_t)xdoc, ref_count);
103
+ return ref_count;
104
+ }
105
+
106
+ void
107
+ ruby_xml_document_free(xmlDocPtr xdoc) {
108
+ int ref_count;
109
+
110
+ if (!st_lookup(ref_count_table, (st_data_t)xdoc, (st_data_t*)&ref_count))
111
+ {
112
+ ruby_xml_document_internal_free(xdoc);
113
+ }
114
+ else if (ref_count == 0)
115
+ {
116
+ ruby_xml_document_internal_free(xdoc);
117
+ }
118
+ else if (ref_count > 0)
119
+ {
120
+ ref_count *= -1;
121
+ st_insert(ref_count_table, (st_data_t)xdoc, ref_count);
122
+ }
123
+ else
124
+ {
125
+ rb_raise(rb_eRuntimeError, "Ruby is attempting to free document twice.");
126
+ }
127
+ }
128
+
129
+ void
130
+ ruby_xml_document_mark(xmlDocPtr xdoc) {
131
+ rb_gc_mark(LIBXML_STATE);
132
+ }
133
+
134
+ VALUE
135
+ ruby_xml_document_wrap(xmlDocPtr xdoc) {
136
+ VALUE result;
137
+
138
+ // This node is already wrapped
139
+ if (xdoc->_private != NULL)
140
+ {
141
+ result = (VALUE)xdoc->_private;
142
+ }
143
+ else
144
+ {
145
+ result = Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark, ruby_xml_document_free, xdoc);
146
+ xdoc->_private = (void*)result;
147
+ }
148
+
149
+ return result;
150
+ }
151
+
152
+
153
+ /*
154
+ * call-seq:
155
+ * XML::Document.alloc(xml_version = 1.0) -> document
156
+ *
157
+ * Alocates a new XML::Document, optionally specifying the
158
+ * XML version.
159
+ */
160
+ VALUE
161
+ ruby_xml_document_alloc(VALUE klass) {
162
+ return Data_Wrap_Struct(klass, ruby_xml_document_mark, ruby_xml_document_free, NULL);
163
+ }
164
+
165
+ /*
166
+ * call-seq:
167
+ * XML::Document.initialize(xml_version = 1.0) -> document
168
+ *
169
+ * Initializes a new XML::Document, optionally specifying the
170
+ * XML version.
171
+ */
172
+ VALUE
173
+ ruby_xml_document_initialize(int argc, VALUE *argv, VALUE self) {
174
+ xmlDocPtr xdoc;
175
+ VALUE xmlver;
176
+
177
+ switch (argc) {
178
+ case 0:
179
+ xmlver = rb_str_new2("1.0");
180
+ break;
181
+ case 1:
182
+ rb_scan_args(argc, argv, "01", &xmlver);
183
+ break;
184
+ default:
185
+ rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
186
+ }
187
+
188
+ Check_Type(xmlver, T_STRING);
189
+ xdoc = xmlNewDoc((xmlChar*)StringValuePtr(xmlver));
190
+ xdoc->_private = (void*)self;
191
+ DATA_PTR(self) = xdoc;
192
+
193
+ return self;
194
+ }
195
+
196
+
197
+ /*
198
+ * call-seq:
199
+ * document.compression -> num
200
+ *
201
+ * Obtain this document's compression mode identifier.
202
+ */
203
+ VALUE
204
+ ruby_xml_document_compression_get(VALUE self) {
205
+ #ifdef HAVE_ZLIB_H
206
+ xmlDocPtr xdoc;
207
+
208
+ int compmode;
209
+ Data_Get_Struct(self, xmlDoc, xdoc);
210
+
211
+ compmode = xmlGetDocCompressMode(xdoc);
212
+ if (compmode == -1)
213
+ return(Qnil);
214
+ else
215
+ return(INT2NUM(compmode));
216
+ #else
217
+ rb_warn("libxml not compiled with zlib support");
218
+ return(Qfalse);
219
+ #endif
220
+ }
221
+
222
+
223
+ /*
224
+ * call-seq:
225
+ * document.compression = num
226
+ *
227
+ * Set this document's compression mode.
228
+ */
229
+ VALUE
230
+ ruby_xml_document_compression_set(VALUE self, VALUE num) {
231
+ #ifdef HAVE_ZLIB_H
232
+ xmlDocPtr xdoc;
233
+
234
+ int compmode;
235
+ Check_Type(num, T_FIXNUM);
236
+ Data_Get_Struct(self, xmlDoc, xdoc);
237
+
238
+ if (xdoc == NULL) {
239
+ return(Qnil);
240
+ } else {
241
+ xmlSetDocCompressMode(xdoc, NUM2INT(num));
242
+
243
+ compmode = xmlGetDocCompressMode(xdoc);
244
+ if (compmode == -1)
245
+ return(Qnil);
246
+ else
247
+ return(INT2NUM(compmode));
248
+ }
249
+ #else
250
+ rb_warn("libxml compiled without zlib support");
251
+ return(Qfalse);
252
+ #endif
253
+ }
254
+
255
+
256
+ /*
257
+ * call-seq:
258
+ * document.compression? -> (true|false)
259
+ *
260
+ * Determine whether this document is compressed.
261
+ */
262
+ VALUE
263
+ ruby_xml_document_compression_q(VALUE self) {
264
+ #ifdef HAVE_ZLIB_H
265
+ xmlDocPtr xdoc;
266
+
267
+ Data_Get_Struct(self, xmlDoc, xdoc);
268
+
269
+ if (xdoc->compression != -1)
270
+ return(Qtrue);
271
+ else
272
+ return(Qfalse);
273
+ #else
274
+ rb_warn("libxml compiled without zlib support");
275
+ return(Qfalse);
276
+ #endif
277
+ }
278
+
279
+
280
+ /*
281
+ * call-seq:
282
+ * document.child -> node
283
+ *
284
+ * Get this document's child node.
285
+ */
286
+ VALUE
287
+ ruby_xml_document_child_get(VALUE self) {
288
+ xmlDocPtr xdoc;
289
+ Data_Get_Struct(self, xmlDoc, xdoc);
290
+
291
+ if (xdoc->children == NULL)
292
+ return(Qnil);
293
+
294
+ return ruby_xml_node2_wrap(cXMLNode, xdoc->children);
295
+ }
296
+
297
+
298
+ /*
299
+ * call-seq:
300
+ * document.child? -> (true|false)
301
+ *
302
+ * Determine whether this document has a child node.
303
+ */
304
+ VALUE
305
+ ruby_xml_document_child_q(VALUE self) {
306
+ xmlDocPtr xdoc;
307
+ Data_Get_Struct(self, xmlDoc, xdoc);
308
+
309
+ if (xdoc->children == NULL)
310
+ return(Qfalse);
311
+ else
312
+ return(Qtrue);
313
+ }
314
+
315
+
316
+ /*
317
+ * call-seq:
318
+ * document.dump([stream]) -> true
319
+ *
320
+ * Dump this document's XML to the specified IO stream.
321
+ * If no stream is specified, stdout is used.
322
+ */
323
+ VALUE
324
+ ruby_xml_document_dump(int argc, VALUE *argv, VALUE self) {
325
+ OpenFile *fptr;
326
+ VALUE io;
327
+ FILE *out;
328
+ xmlDocPtr xdoc;
329
+
330
+ Data_Get_Struct(self, xmlDoc, xdoc);
331
+ if (xdoc == NULL)
332
+ return(Qnil);
333
+
334
+ switch (argc) {
335
+ case 0:
336
+ io = rb_stdout;
337
+ break;
338
+ case 1:
339
+ io = argv[0];
340
+ if (!rb_obj_is_kind_of(io, rb_cIO))
341
+ rb_raise(rb_eTypeError, "need an IO object");
342
+ break;
343
+ default:
344
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
345
+ }
346
+
347
+ GetOpenFile(io, fptr);
348
+ rb_io_check_writable(fptr);
349
+ out = GetWriteFile(fptr);
350
+ xmlDocDump(out, xdoc);
351
+ return(Qtrue);
352
+ }
353
+
354
+
355
+ /*
356
+ * call-seq:
357
+ * document.debug_dump([stream]) -> true
358
+ *
359
+ * Debug version of dump.
360
+ */
361
+ VALUE
362
+ ruby_xml_document_debug_dump(int argc, VALUE *argv, VALUE self) {
363
+ #ifdef LIBXML_DEBUG_ENABLED
364
+ OpenFile *fptr;
365
+ VALUE io;
366
+ FILE *out;
367
+ xmlDocPtr xdoc;
368
+
369
+ Data_Get_Struct(self, xmlDoc, xdoc);
370
+ if (xdoc == NULL)
371
+ return(Qnil);
372
+
373
+ switch (argc) {
374
+ case 0:
375
+ io = rb_stderr;
376
+ break;
377
+ case 1:
378
+ io = argv[0];
379
+ if (!rb_obj_is_kind_of(io, rb_cIO))
380
+ rb_raise(rb_eTypeError, "need an IO object");
381
+ break;
382
+ default:
383
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
384
+ }
385
+
386
+ GetOpenFile(io, fptr);
387
+ rb_io_check_writable(fptr);
388
+ out = GetWriteFile(fptr);
389
+ xmlDebugDumpDocument(out, xdoc);
390
+ return(Qtrue);
391
+ #else
392
+ rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
393
+ return(Qfalse);
394
+ #endif
395
+ }
396
+
397
+
398
+ /*
399
+ * call-seq:
400
+ * document.debug_dump_head([stream]) -> true
401
+ *
402
+ * Debug-dump this document's header to the specified IO stream.
403
+ * If no stream is specified, stdout is used.
404
+ */
405
+ VALUE
406
+ ruby_xml_document_debug_dump_head(int argc, VALUE *argv, VALUE self) {
407
+ #ifdef LIBXML_DEBUG_ENABLED
408
+ OpenFile *fptr;
409
+ VALUE io;
410
+ FILE *out;
411
+ xmlDocPtr xdoc;
412
+
413
+
414
+ Data_Get_Struct(self, xmlDoc, xdoc);
415
+ if (xdoc == NULL)
416
+ return(Qnil);
417
+
418
+ switch (argc) {
419
+ case 0:
420
+ io = rb_stdout;
421
+ break;
422
+ case 1:
423
+ io = argv[0];
424
+ if (!rb_obj_is_kind_of(io, rb_cIO))
425
+ rb_raise(rb_eTypeError, "need an IO object");
426
+ break;
427
+ default:
428
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
429
+ }
430
+
431
+ GetOpenFile(io, fptr);
432
+ rb_io_check_writable(fptr);
433
+ out = GetWriteFile(fptr);
434
+ xmlDebugDumpDocumentHead(out, xdoc);
435
+ return(Qtrue);
436
+ #else
437
+ rb_warn("libxml was compiled without debugging support. Please recompile libxml and ruby-libxml");
438
+ return(Qfalse);
439
+ #endif
440
+ }
441
+
442
+
443
+ /*
444
+ * call-seq:
445
+ * document.format_dump([stream], [spacing]) -> true
446
+ *
447
+ * Dump this document's formatted XML to the specified IO stream.
448
+ * If no stream is specified, stdout is used. If spacing is
449
+ * specified, it must be a boolean that determines whether
450
+ * spacing is used.
451
+ */
452
+ VALUE
453
+ ruby_xml_document_format_dump(int argc, VALUE *argv, VALUE self) {
454
+ OpenFile *fptr;
455
+ VALUE bool, io;
456
+ FILE *out;
457
+ xmlDocPtr xdoc;
458
+
459
+ int size, spacing;
460
+
461
+ Data_Get_Struct(self, xmlDoc, xdoc);
462
+ if (xdoc == NULL)
463
+ return(Qnil);
464
+
465
+ switch (argc) {
466
+ case 0:
467
+ io = rb_stdout;
468
+ spacing = 1;
469
+ break;
470
+ case 1:
471
+ io = argv[0];
472
+ if (!rb_obj_is_kind_of(io, rb_cIO))
473
+ rb_raise(rb_eTypeError, "need an IO object");
474
+ spacing = 1;
475
+ break;
476
+ case 2:
477
+ io = argv[0];
478
+ if (!rb_obj_is_kind_of(io, rb_cIO))
479
+ rb_raise(rb_eTypeError, "need an IO object");
480
+ bool = argv[1];
481
+ if (TYPE(bool) == T_TRUE)
482
+ spacing = 1;
483
+ else if (TYPE(bool) == T_FALSE)
484
+ spacing = 0;
485
+ else
486
+ rb_raise(rb_eTypeError, "incorect argument type, second argument must be bool");
487
+
488
+ break;
489
+ default:
490
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
491
+ }
492
+
493
+ GetOpenFile(io, fptr);
494
+ rb_io_check_writable(fptr);
495
+ out = GetWriteFile(fptr);
496
+ size = xmlDocFormatDump(out, xdoc, spacing);
497
+ return(INT2NUM(size));
498
+ }
499
+
500
+
501
+ /*
502
+ * call-seq:
503
+ * document.debug_format_dump([stream]) -> true
504
+ *
505
+ * *Deprecated* in favour of format_dump.
506
+ */
507
+ VALUE
508
+ ruby_xml_document_debug_format_dump(int argc, VALUE *argv, VALUE self) {
509
+ rb_warn("debug_format_dump has been deprecaited, use format_dump instead");
510
+ return(ruby_xml_document_format_dump(argc, argv, self));
511
+ }
512
+
513
+
514
+ /*
515
+ * call-seq:
516
+ * document.encoding -> "encoding"
517
+ *
518
+ * Obtain the encoding specified by this document.
519
+ */
520
+ VALUE
521
+ ruby_xml_document_encoding_get(VALUE self) {
522
+ xmlDocPtr xdoc;
523
+
524
+ Data_Get_Struct(self, xmlDoc, xdoc);
525
+ if (xdoc->encoding == NULL)
526
+ return(Qnil);
527
+ else
528
+ return(rb_str_new2((const char*)xdoc->encoding));
529
+ }
530
+
531
+
532
+ /*
533
+ * call-seq:
534
+ * document.encoding = "encoding"
535
+ *
536
+ * Set the encoding for this document.
537
+ */
538
+ VALUE
539
+ ruby_xml_document_encoding_set(VALUE self, VALUE encoding) {
540
+ xmlDocPtr xdoc;
541
+
542
+
543
+ Check_Type(encoding, T_STRING);
544
+ Data_Get_Struct(self, xmlDoc, xdoc);
545
+ xdoc->encoding = xmlStrdup(StringValuePtr(encoding));
546
+ return(ruby_xml_document_encoding_get(self));
547
+ }
548
+
549
+ /*
550
+ * call-seq:
551
+ * document.last -> node
552
+ *
553
+ * Obtain the last node.
554
+ */
555
+ VALUE
556
+ ruby_xml_document_last_get(VALUE self) {
557
+ xmlDocPtr xdoc;
558
+
559
+
560
+ Data_Get_Struct(self, xmlDoc, xdoc);
561
+
562
+ if (xdoc->last == NULL)
563
+ return(Qnil);
564
+
565
+ return ruby_xml_node2_wrap(cXMLNode, xdoc->last);
566
+ }
567
+
568
+
569
+ /*
570
+ * call-seq:
571
+ * document.last? -> (true|false)
572
+ *
573
+ * Determine whether there is a last node.
574
+ */
575
+ VALUE
576
+ ruby_xml_document_last_q(VALUE self) {
577
+ xmlDocPtr xdoc;
578
+
579
+ Data_Get_Struct(self, xmlDoc, xdoc);
580
+
581
+ if (xdoc->last == NULL)
582
+ return(Qfalse);
583
+ else
584
+ return(Qtrue);
585
+ }
586
+
587
+
588
+ /*
589
+ * call-seq:
590
+ * document.next -> node
591
+ *
592
+ * Obtain the next node.
593
+ */
594
+ VALUE
595
+ ruby_xml_document_next_get(VALUE self) {
596
+ xmlDocPtr xdoc;
597
+
598
+
599
+ Data_Get_Struct(self, xmlDoc, xdoc);
600
+
601
+ if (xdoc->next == NULL)
602
+ return(Qnil);
603
+
604
+ return ruby_xml_node2_wrap(cXMLNode, xdoc->next);
605
+ }
606
+
607
+
608
+ /*
609
+ * call-seq:
610
+ * document.next? -> (true|false)
611
+ *
612
+ * Determine whether there is a next node.
613
+ */
614
+ VALUE
615
+ ruby_xml_document_next_q(VALUE self) {
616
+ xmlDocPtr xdoc;
617
+
618
+ Data_Get_Struct(self, xmlDoc, xdoc);
619
+
620
+ if (xdoc->next == NULL)
621
+ return(Qfalse);
622
+ else
623
+ return(Qtrue);
624
+ }
625
+
626
+
627
+ /*
628
+ * call-seq:
629
+ * document.parent -> node
630
+ *
631
+ * Obtain the parent node.
632
+ */
633
+ VALUE
634
+ ruby_xml_document_parent_get(VALUE self) {
635
+ xmlDocPtr xdoc;
636
+
637
+
638
+ Data_Get_Struct(self, xmlDoc, xdoc);
639
+
640
+ if (xdoc->parent == NULL)
641
+ return(Qnil);
642
+
643
+ return ruby_xml_node2_wrap(cXMLNode, xdoc->parent);
644
+ }
645
+
646
+
647
+ /*
648
+ * call-seq:
649
+ * document.parent? -> (true|false)
650
+ *
651
+ * Determine whether there is a parent node.
652
+ */
653
+ VALUE
654
+ ruby_xml_document_parent_q(VALUE self) {
655
+ xmlDocPtr xdoc;
656
+
657
+ Data_Get_Struct(self, xmlDoc, xdoc);
658
+
659
+ if (xdoc->parent == NULL)
660
+ return(Qfalse);
661
+ else
662
+ return(Qtrue);
663
+ }
664
+
665
+
666
+ /*
667
+ * call-seq:
668
+ * document.prev -> node
669
+ *
670
+ * Obtain the previous node.
671
+ */
672
+ VALUE
673
+ ruby_xml_document_prev_get(VALUE self) {
674
+ xmlDocPtr xdoc;
675
+
676
+
677
+ Data_Get_Struct(self, xmlDoc, xdoc);
678
+
679
+ if (xdoc->prev == NULL)
680
+ return(Qnil);
681
+
682
+ return ruby_xml_node2_wrap(cXMLNode, xdoc->prev);
683
+ }
684
+
685
+
686
+ /*
687
+ * call-seq:
688
+ * document.prev? -> (true|false)
689
+ *
690
+ * Determine whether there is a previous node.
691
+ */
692
+ VALUE
693
+ ruby_xml_document_prev_q(VALUE self) {
694
+ xmlDocPtr xdoc;
695
+
696
+ Data_Get_Struct(self, xmlDoc, xdoc);
697
+
698
+ if (xdoc->prev == NULL)
699
+ return(Qfalse);
700
+ else
701
+ return(Qtrue);
702
+ }
703
+
704
+
705
+ /*
706
+ * call-seq:
707
+ * document.root -> node
708
+ *
709
+ * Obtain the root node.
710
+ */
711
+ VALUE
712
+ ruby_xml_document_root_get(VALUE self) {
713
+ xmlDocPtr xdoc;
714
+
715
+ xmlNodePtr root;
716
+
717
+ Data_Get_Struct(self, xmlDoc, xdoc);
718
+ root = xmlDocGetRootElement(xdoc);
719
+
720
+ if (root == NULL)
721
+ return(Qnil);
722
+
723
+ return ruby_xml_node2_wrap(cXMLNode, root);
724
+ }
725
+
726
+
727
+ /*
728
+ * call-seq:
729
+ * document.root = node
730
+ *
731
+ * Set the root node.
732
+ */
733
+ VALUE
734
+ ruby_xml_document_root_set(VALUE self, VALUE node) {
735
+ xmlDocPtr xdoc;
736
+ xmlNodePtr xroot, xnode;
737
+
738
+ if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
739
+ rb_raise(rb_eTypeError, "must pass an XML::Node type object");
740
+
741
+ Data_Get_Struct(self, xmlDoc, xdoc);
742
+ Data_Get_Struct(node, xmlNode, xnode);
743
+ xroot = xmlDocSetRootElement(xdoc, xnode);
744
+ if (xroot == NULL)
745
+ return(Qnil);
746
+
747
+ return ruby_xml_node2_wrap(cXMLNode, xroot);
748
+ }
749
+
750
+
751
+ /*
752
+ * call-seq:
753
+ * document.save(filename, format = false) -> int
754
+ *
755
+ * Save this document to the file given by filename,
756
+ * optionally formatting the output.
757
+
758
+ * Parameters:
759
+ * filename: The filename or URL of the new document
760
+ * format: Specifies whether formatting spaces should be added.
761
+ * returns: The number of bytes written or -1 in case of error.
762
+ */
763
+ VALUE
764
+ ruby_xml_document_save(int argc, VALUE *argv, VALUE self) {
765
+ xmlDocPtr xdoc;
766
+
767
+ const char *filename;
768
+ int format = 0;
769
+ int len;
770
+
771
+ if (argc <1 || argc > 2)
772
+ rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
773
+
774
+ Check_Type(argv[0], T_STRING);
775
+ filename = StringValuePtr(argv[0]);
776
+
777
+ if (argc == 2)
778
+ {
779
+ switch (TYPE(argv[1])) {
780
+ case T_TRUE:
781
+ format = 1;
782
+ break;
783
+ case T_FALSE:
784
+ format = 0;
785
+ break;
786
+ default:
787
+ rb_raise(rb_eArgError, "The second parameter (format) must be true or false");
788
+ }
789
+ }
790
+
791
+ Data_Get_Struct(self, xmlDoc, xdoc);
792
+ len = xmlSaveFormatFileEnc(filename, xdoc, (const char*)xdoc->encoding, format);
793
+
794
+ if (len == -1)
795
+ rb_raise(rb_eIOError, "Could not write document");
796
+ else
797
+ return(INT2NUM(len));
798
+ }
799
+
800
+
801
+ /*
802
+ * call-seq:
803
+ * document.standalone? -> (true|false)
804
+ *
805
+ * Determine whether this is a standalone document.
806
+ */
807
+ VALUE
808
+ ruby_xml_document_standalone_q(VALUE self) {
809
+ xmlDocPtr xdoc;
810
+
811
+ Data_Get_Struct(self, xmlDoc, xdoc);
812
+ if (xdoc->standalone)
813
+ return(Qtrue);
814
+ else
815
+ return(Qfalse);
816
+ }
817
+
818
+
819
+ /*
820
+ * call-seq:
821
+ * document.to_s({format=true,encoding) -> "xml"
822
+ *
823
+ * Coerce this document to a string representation
824
+ * of it's XML. The default is to pretty format, but this
825
+ * depends Parser#indent_tree_output==true or
826
+ * Parser#default_keep_blanks==false.
827
+ *
828
+ * The encoding is not applied to the document, but is
829
+ * encoding target of the resulting string.
830
+ */
831
+ VALUE
832
+ ruby_xml_document_to_s(int argc, VALUE *argv, VALUE self) {
833
+ xmlDocPtr xdoc;
834
+
835
+ xmlChar *result, *encoding=NULL;
836
+ int format, len;
837
+ VALUE rresult;
838
+
839
+ switch (argc) {
840
+ case 0:
841
+ format = 1;
842
+ break;
843
+ case 2:
844
+ if (TYPE(argv[1]) == T_STRING)
845
+ encoding=(xmlChar *)StringValuePtr(argv[1]);
846
+ case 1:
847
+ if (TYPE(argv[0]) == T_TRUE)
848
+ format = 1;
849
+ else if (TYPE(argv[0]) == T_FALSE)
850
+ format = 0;
851
+ else
852
+ rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
853
+ break;
854
+ default:
855
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
856
+ }
857
+
858
+ Data_Get_Struct(self, xmlDoc, xdoc);
859
+ if (xdoc == NULL) {
860
+ return(Qnil);
861
+ } else if (encoding != NULL) {
862
+ if (format) {
863
+ xmlDocDumpFormatMemoryEnc(xdoc, &result, &len,
864
+ (const char*)encoding, format);
865
+ } else {
866
+ xmlDocDumpMemoryEnc(xdoc, &result, &len,
867
+ (const char *)encoding);
868
+ }
869
+ } else {
870
+ if (format)
871
+ xmlDocDumpFormatMemory(xdoc, &result, &len, format);
872
+ else
873
+ xmlDocDumpMemory(xdoc, &result, &len);
874
+ }
875
+ rresult=rb_str_new((const char*)result,len);
876
+ xmlFree(result);
877
+ return rresult;
878
+ }
879
+
880
+
881
+ /*
882
+ * call-seq:
883
+ * document.url -> "url"
884
+ *
885
+ * Obtain this document's source URL, if any.
886
+ */
887
+ VALUE
888
+ ruby_xml_document_url_get(VALUE self) {
889
+ xmlDocPtr xdoc;
890
+
891
+ Data_Get_Struct(self, xmlDoc, xdoc);
892
+ if (xdoc->URL == NULL)
893
+ return(Qnil);
894
+ else
895
+ return(rb_str_new2((const char*)xdoc->URL));
896
+ }
897
+
898
+
899
+ /*
900
+ * call-seq:
901
+ * document.version -> "version"
902
+ *
903
+ * Obtain the XML version specified by this document.
904
+ */
905
+ VALUE
906
+ ruby_xml_document_version_get(VALUE self) {
907
+ xmlDocPtr xdoc;
908
+
909
+ Data_Get_Struct(self, xmlDoc, xdoc);
910
+ if (xdoc->version == NULL)
911
+ return(Qnil);
912
+ else
913
+ return(rb_str_new2((const char*)xdoc->version));
914
+ }
915
+
916
+
917
+ /*
918
+ * call-seq:
919
+ * document.xinclude -> num
920
+ *
921
+ * Process xinclude directives in this document.
922
+ */
923
+ VALUE
924
+ ruby_xml_document_xinclude(VALUE self) {
925
+ #ifdef LIBXML_XINCLUDE_ENABLED
926
+ xmlDocPtr xdoc;
927
+
928
+ int ret;
929
+
930
+ Data_Get_Struct(self, xmlDoc, xdoc);
931
+ ret = xmlXIncludeProcess(xdoc);
932
+ if (ret >= 0)
933
+ {
934
+ return(INT2NUM(ret));
935
+ }
936
+ else
937
+ {
938
+ ruby_xml_raise(&xmlLastError);
939
+ return Qnil;
940
+ }
941
+ #else
942
+ rb_warn("libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
943
+ return(Qfalse);
944
+ #endif
945
+ }
946
+
947
+ void
948
+ LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
949
+ {
950
+ if (rb_block_given_p()) {
951
+ char buff[1024];
952
+ snprintf(buff, 1024, msg, ap);
953
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
954
+ } else {
955
+ fprintf(stderr, "error -- found validity error: ");
956
+ fprintf(stderr, msg, ap);
957
+ }
958
+ }
959
+
960
+ void
961
+ LibXML_validity_warning(void * ctxt, const char * msg, va_list ap)
962
+ {
963
+ if (rb_block_given_p()) {
964
+ char buff[1024];
965
+ snprintf(buff, 1024, msg, ap);
966
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qfalse));
967
+ } else {
968
+ fprintf(stderr, "warning -- found validity error: ");
969
+ fprintf(stderr, msg, ap);
970
+ }
971
+ }
972
+
973
+ /*
974
+ * call-seq:
975
+ * document.validate_schema(schema) -> (true|false)
976
+ *
977
+ * Validate this document against the specified XML::Schema.
978
+ *
979
+ * If a block is provided it is used as an error handler for validaten errors.
980
+ * The block is called with two argument, the message and a flag indication
981
+ * if the message is an error (true) or a warning (false).
982
+ */
983
+ VALUE
984
+ ruby_xml_document_validate_schema(VALUE self, VALUE schema) {
985
+ xmlSchemaValidCtxtPtr vptr;
986
+ xmlDocPtr xdoc;
987
+ ruby_xml_schema *c_schema;
988
+ int is_invalid;
989
+
990
+ Data_Get_Struct(self, xmlDoc, xdoc);
991
+ Data_Get_Struct(schema, ruby_xml_schema, c_schema);
992
+
993
+ vptr = xmlSchemaNewValidCtxt(c_schema->schema);
994
+
995
+ xmlSchemaSetValidErrors(vptr, (xmlSchemaValidityErrorFunc)LibXML_validity_error,
996
+ (xmlSchemaValidityWarningFunc)LibXML_validity_warning, NULL);
997
+
998
+ is_invalid = xmlSchemaValidateDoc(vptr, xdoc);
999
+ xmlSchemaFreeValidCtxt(vptr);
1000
+ if (is_invalid)
1001
+ {
1002
+ ruby_xml_raise(&xmlLastError);
1003
+ return Qfalse;
1004
+ } else
1005
+ {
1006
+ return Qtrue;
1007
+ }
1008
+ }
1009
+
1010
+ /*
1011
+ * call-seq:
1012
+ * document.validate_schema(relaxng) -> (true|false)
1013
+ *
1014
+ * Validate this document against the specified XML::RelaxNG.
1015
+ *
1016
+ * If a block is provided it is used as an error handler for validaten errors.
1017
+ * The block is called with two argument, the message and a flag indication
1018
+ * if the message is an error (true) or a warning (false).
1019
+ */
1020
+ VALUE
1021
+ ruby_xml_document_validate_relaxng(VALUE self, VALUE relaxng) {
1022
+ xmlRelaxNGValidCtxtPtr vptr;
1023
+ xmlDocPtr xdoc;
1024
+ ruby_xml_relaxng *c_relaxng;
1025
+ int is_invalid;
1026
+
1027
+ Data_Get_Struct(self, xmlDoc, xdoc);
1028
+ Data_Get_Struct(relaxng, ruby_xml_relaxng, c_relaxng);
1029
+
1030
+ vptr = xmlRelaxNGNewValidCtxt(c_relaxng->relaxng);
1031
+
1032
+ xmlRelaxNGSetValidErrors(vptr, (xmlRelaxNGValidityErrorFunc)LibXML_validity_error,
1033
+ (xmlRelaxNGValidityWarningFunc)LibXML_validity_warning, NULL);
1034
+
1035
+ is_invalid = xmlRelaxNGValidateDoc(vptr, xdoc);
1036
+ xmlRelaxNGFreeValidCtxt(vptr);
1037
+ if (is_invalid)
1038
+ {
1039
+ ruby_xml_raise(&xmlLastError);
1040
+ return Qfalse;
1041
+ } else
1042
+ {
1043
+ return Qtrue;
1044
+ }
1045
+ }
1046
+
1047
+
1048
+ /*
1049
+ * call-seq:
1050
+ * document.validate(dtd) -> (true|false)
1051
+ *
1052
+ * Validate this document against the specified XML::DTD.
1053
+ */
1054
+ VALUE
1055
+ ruby_xml_document_validate_dtd(VALUE self, VALUE dtd) {
1056
+ VALUE error = Qnil;
1057
+ xmlValidCtxt ctxt;
1058
+ xmlDocPtr xdoc;
1059
+ ruby_xml_dtd *c_dtd;
1060
+
1061
+ Data_Get_Struct(self, xmlDoc, xdoc);
1062
+ Data_Get_Struct(dtd, ruby_xml_dtd, c_dtd);
1063
+
1064
+ ctxt.userData = &error;
1065
+ ctxt.error = (xmlValidityErrorFunc)LibXML_validity_error;
1066
+ ctxt.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
1067
+
1068
+ ctxt.nodeNr = 0;
1069
+ ctxt.nodeTab = NULL;
1070
+ ctxt.vstateNr = 0;
1071
+ ctxt.vstateTab = NULL;
1072
+
1073
+ if (xmlValidateDtd(&ctxt, xdoc, c_dtd->dtd))
1074
+ {
1075
+ return(Qtrue);
1076
+ }
1077
+ else
1078
+ {
1079
+ ruby_xml_raise(&xmlLastError);
1080
+ return Qfalse;
1081
+ }
1082
+ }
1083
+
1084
+
1085
+ /*
1086
+ * call-seq:
1087
+ * document.reader -> reader
1088
+ *
1089
+ * Create a XML::Reader from the document. This is a shortcut to
1090
+ * XML::Reader.walker().
1091
+ */
1092
+ static VALUE
1093
+ ruby_xml_document_reader(VALUE self)
1094
+ {
1095
+ return ruby_xml_reader_new_walker(cXMLReader, self);
1096
+ }
1097
+
1098
+ // Rdoc needs to know
1099
+ #ifdef RDOC_NEVER_DEFINED
1100
+ mLibXML = rb_define_module("LibXML");
1101
+ mXML = rb_define_module_under(mLibXML, "XML");
1102
+ #endif
1103
+
1104
+ void
1105
+ ruby_init_xml_document(void) {
1106
+ ref_count_table = st_init_numtable();
1107
+
1108
+ cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
1109
+ rb_define_alloc_func(cXMLDocument, ruby_xml_document_alloc);
1110
+
1111
+ rb_define_method(cXMLDocument, "initialize", ruby_xml_document_initialize, -1);
1112
+ rb_define_method(cXMLDocument, "child", ruby_xml_document_child_get, 0);
1113
+ rb_define_method(cXMLDocument, "child?", ruby_xml_document_child_q, 0);
1114
+ rb_define_method(cXMLDocument, "compression", ruby_xml_document_compression_get, 0);
1115
+ rb_define_method(cXMLDocument, "compression=", ruby_xml_document_compression_set, 1);
1116
+ rb_define_method(cXMLDocument, "compression?", ruby_xml_document_compression_q, 0);
1117
+ rb_define_method(cXMLDocument, "dump", ruby_xml_document_dump, -1);
1118
+ rb_define_method(cXMLDocument, "debug_dump", ruby_xml_document_debug_dump, -1);
1119
+ rb_define_method(cXMLDocument, "debug_dump_head", ruby_xml_document_debug_dump_head, -1);
1120
+ rb_define_method(cXMLDocument, "debug_format_dump", ruby_xml_document_debug_format_dump, -1);
1121
+ rb_define_method(cXMLDocument, "encoding", ruby_xml_document_encoding_get, 0);
1122
+ rb_define_method(cXMLDocument, "encoding=", ruby_xml_document_encoding_set, 1);
1123
+ rb_define_method(cXMLDocument, "format_dump", ruby_xml_document_format_dump, -1);
1124
+ rb_define_method(cXMLDocument, "last", ruby_xml_document_last_get, 0);
1125
+ rb_define_method(cXMLDocument, "last?", ruby_xml_document_last_q, 0);
1126
+ rb_define_method(cXMLDocument, "next", ruby_xml_document_next_get, 0);
1127
+ rb_define_method(cXMLDocument, "next?", ruby_xml_document_next_q, 0);
1128
+ rb_define_method(cXMLDocument, "parent", ruby_xml_document_parent_get, 0);
1129
+ rb_define_method(cXMLDocument, "parent?", ruby_xml_document_parent_q, 0);
1130
+ rb_define_method(cXMLDocument, "prev", ruby_xml_document_prev_get, 0);
1131
+ rb_define_method(cXMLDocument, "prev?", ruby_xml_document_prev_q, 0);
1132
+ rb_define_method(cXMLDocument, "root", ruby_xml_document_root_get, 0);
1133
+ rb_define_method(cXMLDocument, "root=", ruby_xml_document_root_set, 1);
1134
+ rb_define_method(cXMLDocument, "save", ruby_xml_document_save, -1);
1135
+ rb_define_method(cXMLDocument, "standalone?", ruby_xml_document_standalone_q, 0);
1136
+ rb_define_method(cXMLDocument, "to_s", ruby_xml_document_to_s, -1);
1137
+ rb_define_method(cXMLDocument, "url", ruby_xml_document_url_get, 0);
1138
+ rb_define_method(cXMLDocument, "version", ruby_xml_document_version_get, 0);
1139
+ rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
1140
+ rb_define_method(cXMLDocument, "validate", ruby_xml_document_validate_dtd, 1);
1141
+ rb_define_method(cXMLDocument, "validate_schema", ruby_xml_document_validate_schema, 1);
1142
+ rb_define_method(cXMLDocument, "validate_relaxng", ruby_xml_document_validate_relaxng, 1);
1143
+ rb_define_method(cXMLDocument, "reader", ruby_xml_document_reader, 0);
1144
+ }