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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+ }