libxml-ruby 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/CHANGES +41 -1
  2. data/LICENSE +3 -4
  3. data/README +37 -24
  4. data/Rakefile +2 -2
  5. data/ext/libxml/extconf.rb +31 -12
  6. data/ext/libxml/libxml.c +56 -858
  7. data/ext/libxml/ruby_libxml.h +93 -96
  8. data/ext/libxml/ruby_xml.c +855 -0
  9. data/ext/libxml/ruby_xml.h +9 -0
  10. data/ext/libxml/ruby_xml_attr.c +3 -9
  11. data/ext/libxml/ruby_xml_attr.h +2 -2
  12. data/ext/libxml/ruby_xml_attr_decl.c +2 -8
  13. data/ext/libxml/ruby_xml_attr_decl.h +1 -1
  14. data/ext/libxml/ruby_xml_attributes.c +6 -8
  15. data/ext/libxml/ruby_xml_attributes.h +1 -1
  16. data/ext/libxml/ruby_xml_document.c +915 -895
  17. data/ext/libxml/ruby_xml_document.h +2 -2
  18. data/ext/libxml/ruby_xml_dtd.c +257 -136
  19. data/ext/libxml/ruby_xml_dtd.h +1 -1
  20. data/ext/libxml/ruby_xml_encoding.c +55 -37
  21. data/ext/libxml/ruby_xml_encoding.h +1 -1
  22. data/ext/libxml/ruby_xml_error.c +526 -1058
  23. data/ext/libxml/ruby_xml_error.h +1 -1
  24. data/ext/libxml/ruby_xml_html_parser.c +2 -8
  25. data/ext/libxml/ruby_xml_html_parser.h +2 -2
  26. data/ext/libxml/ruby_xml_html_parser_context.c +175 -145
  27. data/ext/libxml/ruby_xml_html_parser_context.h +1 -1
  28. data/ext/libxml/ruby_xml_html_parser_options.c +12 -20
  29. data/ext/libxml/ruby_xml_html_parser_options.h +1 -1
  30. data/ext/libxml/ruby_xml_input_cbg.c +2 -8
  31. data/ext/libxml/ruby_xml_input_cbg.h +1 -1
  32. data/ext/libxml/ruby_xml_namespace.c +2 -8
  33. data/ext/libxml/ruby_xml_namespace.h +2 -2
  34. data/ext/libxml/ruby_xml_namespaces.c +1 -9
  35. data/ext/libxml/ruby_xml_namespaces.h +1 -1
  36. data/ext/libxml/ruby_xml_node.c +182 -121
  37. data/ext/libxml/ruby_xml_node.h +2 -2
  38. data/ext/libxml/ruby_xml_parser.c +2 -8
  39. data/ext/libxml/ruby_xml_parser.h +2 -2
  40. data/ext/libxml/ruby_xml_parser_context.c +952 -901
  41. data/ext/libxml/ruby_xml_parser_context.h +2 -2
  42. data/ext/libxml/ruby_xml_parser_options.c +2 -9
  43. data/ext/libxml/ruby_xml_parser_options.h +1 -1
  44. data/ext/libxml/ruby_xml_reader.c +1002 -993
  45. data/ext/libxml/ruby_xml_reader.h +1 -1
  46. data/ext/libxml/ruby_xml_relaxng.c +1 -7
  47. data/ext/libxml/ruby_xml_relaxng.h +1 -1
  48. data/ext/libxml/ruby_xml_sax2_handler.c +2 -2
  49. data/ext/libxml/ruby_xml_sax2_handler.h +1 -1
  50. data/ext/libxml/ruby_xml_sax_parser.c +2 -8
  51. data/ext/libxml/ruby_xml_sax_parser.h +2 -2
  52. data/ext/libxml/ruby_xml_schema.c +1 -7
  53. data/ext/libxml/ruby_xml_schema.h +1 -1
  54. data/ext/libxml/{version.h → ruby_xml_version.h} +2 -2
  55. data/ext/libxml/ruby_xml_xinclude.c +2 -8
  56. data/ext/libxml/ruby_xml_xinclude.h +2 -2
  57. data/ext/libxml/ruby_xml_xpath.c +17 -18
  58. data/ext/libxml/ruby_xml_xpath.h +2 -2
  59. data/ext/libxml/ruby_xml_xpath_context.c +387 -389
  60. data/ext/libxml/ruby_xml_xpath_context.h +2 -2
  61. data/ext/libxml/ruby_xml_xpath_expression.c +18 -8
  62. data/ext/libxml/ruby_xml_xpath_expression.h +1 -1
  63. data/ext/libxml/ruby_xml_xpath_object.c +19 -8
  64. data/ext/libxml/ruby_xml_xpath_object.h +1 -1
  65. data/ext/libxml/ruby_xml_xpointer.c +2 -8
  66. data/ext/libxml/ruby_xml_xpointer.h +2 -2
  67. data/ext/vc/libxml_ruby.sln +7 -1
  68. data/lib/libxml.rb +1 -12
  69. data/lib/libxml/attr.rb +0 -3
  70. data/lib/libxml/attr_decl.rb +0 -3
  71. data/lib/libxml/attributes.rb +0 -3
  72. data/lib/libxml/document.rb +31 -5
  73. data/lib/libxml/error.rb +8 -4
  74. data/lib/libxml/properties.rb +0 -5
  75. data/lib/libxml/sax_callbacks.rb +30 -19
  76. data/lib/libxml/tree.rb +0 -1
  77. data/lib/libxml/xpath_object.rb +0 -13
  78. data/test/model/definition.dtd +8 -0
  79. data/test/tc_attributes.rb +4 -1
  80. data/test/tc_document.rb +16 -0
  81. data/test/tc_dtd.rb +30 -2
  82. data/test/tc_html_parser.rb +55 -10
  83. data/test/tc_node.rb +67 -1
  84. data/test/tc_node_edit.rb +26 -6
  85. data/test/tc_node_text.rb +41 -23
  86. data/test/tc_parser.rb +50 -0
  87. data/test/tc_reader.rb +15 -0
  88. data/test/tc_relaxng.rb +1 -1
  89. data/test/tc_sax_parser.rb +37 -5
  90. data/test/tc_schema.rb +1 -1
  91. data/test/tc_xpath.rb +1 -0
  92. data/test/tc_xpath_expression.rb +4 -2
  93. metadata +6 -6
  94. data/ext/libxml/ruby_xml_state.c +0 -51
  95. data/ext/libxml/ruby_xml_state.h +0 -11
  96. data/ext/vc/libxml_ruby.vcproj +0 -460
@@ -0,0 +1,9 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RUBY_XML_H__
4
+ #define __RUBY_XML_H__
5
+
6
+ extern VALUE mXML;
7
+ void rxml_init_xml(void);
8
+
9
+ #endif
@@ -1,11 +1,11 @@
1
- /* $Id: ruby_xml_attr.c 739 2009-01-23 03:42:09Z cfis $ */
1
+ /* $Id: ruby_xml_attr.c 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
5
5
  /*
6
6
  * Document-class: LibXML::XML::Attr
7
7
  *
8
- * Provides access to an single element attribute.
8
+ * Provides access to an attribute defined on an element.
9
9
  *
10
10
  * Basic Usage:
11
11
  *
@@ -327,13 +327,7 @@ VALUE rxml_attr_value_set(VALUE self, VALUE val)
327
327
  return (self);
328
328
  }
329
329
 
330
- // Rdoc needs to know
331
- #ifdef RDOC_NEVER_DEFINED
332
- mLibXML = rb_define_module("LibXML");
333
- mXML = rb_define_module_under(mLibXML, "XML");
334
- #endif
335
-
336
- void ruby_init_xml_attr(void)
330
+ void rxml_init_attr(void)
337
331
  {
338
332
  cXMLAttr = rb_define_class_under(mXML, "Attr", rb_cObject);
339
333
  rb_define_alloc_func(cXMLAttr, rxml_attr_alloc);
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_attr.h 712 2009-01-20 08:08:52Z cfis $ */
1
+ /* $Id: ruby_xml_attr.h 758 2009-01-25 20:36:03Z cfis $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  extern VALUE cXMLAttr;
9
9
 
10
- void ruby_init_xml_attr(void);
10
+ void rxml_init_attr(void);
11
11
  VALUE rxml_attr_wrap(xmlAttrPtr xattr);
12
12
  VALUE rxml_attr_value_get(VALUE self);
13
13
  VALUE rxml_attr_value_set(VALUE self, VALUE val);
@@ -8,7 +8,7 @@
8
8
  * At attribute declaration is used in XML::Dtds to define
9
9
  * what attributes are allowed on an element. An attribute
10
10
  * declaration defines an attribues name, data type and default
11
- * value (if any).
11
+ * value (if any).
12
12
  */
13
13
 
14
14
  #include "ruby_libxml.h"
@@ -158,13 +158,7 @@ VALUE rxml_attr_decl_value_get(VALUE self)
158
158
  return Qnil;
159
159
  }
160
160
 
161
- // Rdoc needs to know
162
- #ifdef RDOC_NEVER_DEFINED
163
- mLibXML = rb_define_module("LibXML");
164
- mXML = rb_define_module_under(mLibXML, "XML");
165
- #endif
166
-
167
- void ruby_init_xml_attr_decl(void)
161
+ void rxml_init_attr_decl(void)
168
162
  {
169
163
  cXMLAttrDecl = rb_define_class_under(mXML, "AttrDecl", rb_cObject);
170
164
  rb_define_method(cXMLAttrDecl, "doc", rxml_attr_decl_doc_get, 0);
@@ -7,7 +7,7 @@
7
7
 
8
8
  extern VALUE cXMLAttrDecl;
9
9
 
10
- void ruby_init_xml_attr_decl(void);
10
+ void rxml_init_attr_decl(void);
11
11
  VALUE rxml_attr_decl_wrap(xmlAttributePtr xattribute);
12
12
  VALUE rxml_attr_decl_value_get(VALUE self);
13
13
  #endif
@@ -199,9 +199,13 @@ static VALUE rxml_attributes_each(VALUE self)
199
199
 
200
200
  while (xattr)
201
201
  {
202
+ /* Get the next attribute while we still can - the user
203
+ may remove the yielded attribute. */
204
+ xmlAttrPtr next = xattr->next;
205
+
202
206
  VALUE attr = rxml_attr_wrap(xattr);
203
207
  rb_yield(attr);
204
- xattr = xattr->next;
208
+ xattr = next;
205
209
  }
206
210
 
207
211
  return self;
@@ -258,13 +262,7 @@ static VALUE rxml_attributes_first(VALUE self)
258
262
  return Qnil;
259
263
  }
260
264
 
261
- // Rdoc needs to know
262
- #ifdef RDOC_NEVER_DEFINED
263
- mLibXML = rb_define_module("LibXML");
264
- mXML = rb_define_module_under(mLibXML, "XML");
265
- #endif
266
-
267
- void ruby_init_xml_attributes(void)
265
+ void rxml_init_attributes(void)
268
266
  {
269
267
  cXMLAttributes = rb_define_class_under(mXML, "Attributes", rb_cObject);
270
268
  rb_include_module(cXMLAttributes, rb_mEnumerable);
@@ -7,7 +7,7 @@
7
7
 
8
8
  extern VALUE cXMLAttributesibutes;
9
9
 
10
- void ruby_init_xml_attributes(void);
10
+ void rxml_init_attributes(void);
11
11
  VALUE rxml_attributes_new(xmlNodePtr xnode);
12
12
 
13
13
  VALUE rxml_attributes_attribute_get(VALUE self, VALUE name);
@@ -1,895 +1,915 @@
1
- /* $Id: ruby_xml_document.c 735 2009-01-22 20:00:04Z 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(filename, :indent => true, :encoding => 'UTF-8')
17
- *
18
- * To read a document from a file:
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
- * To write a file:
29
- *
30
- *
31
- * doc = XML::Document.new()
32
- * doc.root = XML::Node.new('root_node')
33
- * root = doc.root
34
- *
35
- * root << elem1 = XML::Node.new('elem1')
36
- * elem1['attr1'] = 'val1'
37
- * elem1['attr2'] = 'val2'
38
- *
39
- * root << elem2 = XML::Node.new('elem2')
40
- * elem2['attr1'] = 'val1'
41
- * elem2['attr2'] = 'val2'
42
- *
43
- * root << elem3 = XML::Node.new('elem3')
44
- * elem3 << elem4 = XML::Node.new('elem4')
45
- * elem3 << elem5 = XML::Node.new('elem5')
46
- *
47
- * elem5 << elem6 = XML::Node.new('elem6')
48
- * elem6 << 'Content for element 6'
49
- *
50
- * elem3['attr'] = 'baz'
51
- *
52
- * doc.save(filename, :indent => true, :encoding => 'UTF-8')
53
- */
54
-
55
- #include <stdarg.h>
56
- #include <st.h>
57
- #include "ruby_libxml.h"
58
- #include "ruby_xml_document.h"
59
-
60
- VALUE cXMLDocument;
61
-
62
-
63
- void rxml_document_free(xmlDocPtr xdoc)
64
- {
65
- xdoc->_private = NULL;
66
- xmlFreeDoc(xdoc);
67
- }
68
-
69
- void rxml_document_mark(xmlDocPtr xdoc)
70
- {
71
- rb_gc_mark(LIBXML_STATE);
72
- }
73
-
74
- VALUE rxml_document_wrap(xmlDocPtr xdoc)
75
- {
76
- VALUE result;
77
-
78
- // This node is already wrapped
79
- if (xdoc->_private != NULL)
80
- {
81
- result = (VALUE) xdoc->_private;
82
- }
83
- else
84
- {
85
- result = Data_Wrap_Struct(cXMLDocument, rxml_document_mark,
86
- rxml_document_free, xdoc);
87
- xdoc->_private = (void*) result;
88
- }
89
-
90
- return result;
91
- }
92
-
93
- static void LibXML_validity_warning(void * ctxt, const char * msg, va_list ap)
94
- {
95
- if (rb_block_given_p())
96
- {
97
- char buff[1024];
98
- snprintf(buff, 1024, msg, ap);
99
- rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qfalse));
100
- }
101
- else
102
- {
103
- fprintf(stderr, "warning -- found validity error: ");
104
- fprintf(stderr, msg, ap);
105
- }
106
- }
107
-
108
- /*
109
- * call-seq:
110
- * XML::Document.alloc(xml_version = 1.0) -> document
111
- *
112
- * Alocates a new XML::Document, optionally specifying the
113
- * XML version.
114
- */
115
- static VALUE rxml_document_alloc(VALUE klass)
116
- {
117
- return Data_Wrap_Struct(klass, rxml_document_mark, rxml_document_free, NULL);
118
- }
119
-
120
- /*
121
- * call-seq:
122
- * XML::Document.initialize(xml_version = 1.0) -> document
123
- *
124
- * Initializes a new XML::Document, optionally specifying the
125
- * XML version.
126
- */
127
- static VALUE rxml_document_initialize(int argc, VALUE *argv, VALUE self)
128
- {
129
- xmlDocPtr xdoc;
130
- VALUE xmlver;
131
-
132
- switch (argc)
133
- {
134
- case 0:
135
- xmlver = rb_str_new2("1.0");
136
- break;
137
- case 1:
138
- rb_scan_args(argc, argv, "01", &xmlver);
139
- break;
140
- default:
141
- rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
142
- }
143
-
144
- Check_Type(xmlver, T_STRING);
145
- xdoc = xmlNewDoc((xmlChar*) StringValuePtr(xmlver));
146
- xdoc->_private = (void*) self;
147
- DATA_PTR( self) = xdoc;
148
-
149
- return self;
150
- }
151
-
152
- /*
153
- * call-seq:
154
- * document.compression -> num
155
- *
156
- * Obtain this document's compression mode identifier.
157
- */
158
- static VALUE rxml_document_compression_get(VALUE self)
159
- {
160
- #ifdef HAVE_ZLIB_H
161
- xmlDocPtr xdoc;
162
-
163
- int compmode;
164
- Data_Get_Struct(self, xmlDoc, xdoc);
165
-
166
- compmode = xmlGetDocCompressMode(xdoc);
167
- if (compmode == -1)
168
- return(Qnil);
169
- else
170
- return(INT2NUM(compmode));
171
- #else
172
- rb_warn("libxml not compiled with zlib support");
173
- return (Qfalse);
174
- #endif
175
- }
176
-
177
- /*
178
- * call-seq:
179
- * document.compression = num
180
- *
181
- * Set this document's compression mode.
182
- */
183
- static VALUE rxml_document_compression_set(VALUE self, VALUE num)
184
- {
185
- #ifdef HAVE_ZLIB_H
186
- xmlDocPtr xdoc;
187
-
188
- int compmode;
189
- Check_Type(num, T_FIXNUM);
190
- Data_Get_Struct(self, xmlDoc, xdoc);
191
-
192
- if (xdoc == NULL)
193
- {
194
- return(Qnil);
195
- }
196
- else
197
- {
198
- xmlSetDocCompressMode(xdoc, NUM2INT(num));
199
-
200
- compmode = xmlGetDocCompressMode(xdoc);
201
- if (compmode == -1)
202
- return(Qnil);
203
- else
204
- return(INT2NUM(compmode));
205
- }
206
- #else
207
- rb_warn("libxml compiled without zlib support");
208
- return (Qfalse);
209
- #endif
210
- }
211
-
212
- /*
213
- * call-seq:
214
- * document.compression? -> (true|false)
215
- *
216
- * Determine whether this document is compressed.
217
- */
218
- static VALUE rxml_document_compression_q(VALUE self)
219
- {
220
- #ifdef HAVE_ZLIB_H
221
- xmlDocPtr xdoc;
222
-
223
- Data_Get_Struct(self, xmlDoc, xdoc);
224
-
225
- if (xdoc->compression != -1)
226
- return(Qtrue);
227
- else
228
- return(Qfalse);
229
- #else
230
- rb_warn("libxml compiled without zlib support");
231
- return (Qfalse);
232
- #endif
233
- }
234
-
235
- /*
236
- * call-seq:
237
- * document.child -> node
238
- *
239
- * Get this document's child node.
240
- */
241
- static VALUE rxml_document_child_get(VALUE self)
242
- {
243
- xmlDocPtr xdoc;
244
- Data_Get_Struct(self, xmlDoc, xdoc);
245
-
246
- if (xdoc->children == NULL)
247
- return (Qnil);
248
-
249
- return rxml_node_wrap(xdoc->children);
250
- }
251
-
252
- /*
253
- * call-seq:
254
- * document.child? -> (true|false)
255
- *
256
- * Determine whether this document has a child node.
257
- */
258
- static VALUE rxml_document_child_q(VALUE self)
259
- {
260
- xmlDocPtr xdoc;
261
- Data_Get_Struct(self, xmlDoc, xdoc);
262
-
263
- if (xdoc->children == NULL)
264
- return (Qfalse);
265
- else
266
- return (Qtrue);
267
- }
268
-
269
-
270
- /*
271
- * call-seq:
272
- * node.debug -> true|false
273
- *
274
- * Print libxml debugging information to stdout.
275
- * Requires that libxml was compiled with debugging enabled.
276
- */
277
- static VALUE rxml_document_debug(VALUE self)
278
- {
279
- #ifdef LIBXML_DEBUG_ENABLED
280
- xmlDocPtr xdoc;
281
- Data_Get_Struct(self, xmlDoc, xdoc);
282
- xmlDebugDumpDocument(NULL, xdoc);
283
- return Qtrue;
284
- #else
285
- rb_warn("libxml was compiled without debugging support.")
286
- return Qfalse;
287
- #endif
288
- }
289
-
290
- /*
291
- * call-seq:
292
- * document.encoding -> XML::Encoding::UTF_8
293
- *
294
- * Obtain the encoding specified by this document.
295
- */
296
- static VALUE rxml_document_encoding_get(VALUE self)
297
- {
298
- xmlDocPtr xdoc;
299
- Data_Get_Struct(self, xmlDoc, xdoc);
300
-
301
- return INT2NUM(xmlParseCharEncoding(xdoc->encoding));
302
- }
303
-
304
- /*
305
- * call-seq:
306
- * document.encoding = XML::Encoding::UTF_8
307
- *
308
- * Set the encoding for this document.
309
- */
310
- static VALUE rxml_document_encoding_set(VALUE self, VALUE encoding)
311
- {
312
- xmlDocPtr xdoc;
313
- const char* xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(encoding));
314
-
315
- Data_Get_Struct(self, xmlDoc, xdoc);
316
-
317
- if (xdoc->encoding != NULL)
318
- xmlFree((xmlChar *) xdoc->encoding);
319
-
320
- xdoc->encoding = xmlStrdup((xmlChar *)xencoding);
321
- return self;
322
- }
323
-
324
- /*
325
- * call-seq:
326
- * document.last -> node
327
- *
328
- * Obtain the last node.
329
- */
330
- static VALUE rxml_document_last_get(VALUE self)
331
- {
332
- xmlDocPtr xdoc;
333
-
334
- Data_Get_Struct(self, xmlDoc, xdoc);
335
-
336
- if (xdoc->last == NULL)
337
- return (Qnil);
338
-
339
- return rxml_node_wrap(xdoc->last);
340
- }
341
-
342
- /*
343
- * call-seq:
344
- * document.last? -> (true|false)
345
- *
346
- * Determine whether there is a last node.
347
- */
348
- static VALUE rxml_document_last_q(VALUE self)
349
- {
350
- xmlDocPtr xdoc;
351
-
352
- Data_Get_Struct(self, xmlDoc, xdoc);
353
-
354
- if (xdoc->last == NULL)
355
- return (Qfalse);
356
- else
357
- return (Qtrue);
358
- }
359
-
360
- /*
361
- * call-seq:
362
- * document.next -> node
363
- *
364
- * Obtain the next node.
365
- */
366
- static VALUE rxml_document_next_get(VALUE self)
367
- {
368
- xmlDocPtr xdoc;
369
-
370
- Data_Get_Struct(self, xmlDoc, xdoc);
371
-
372
- if (xdoc->next == NULL)
373
- return (Qnil);
374
-
375
- return rxml_node_wrap(xdoc->next);
376
- }
377
-
378
- /*
379
- * call-seq:
380
- * document.next? -> (true|false)
381
- *
382
- * Determine whether there is a next node.
383
- */
384
- static VALUE rxml_document_next_q(VALUE self)
385
- {
386
- xmlDocPtr xdoc;
387
-
388
- Data_Get_Struct(self, xmlDoc, xdoc);
389
-
390
- if (xdoc->next == NULL)
391
- return (Qfalse);
392
- else
393
- return (Qtrue);
394
- }
395
-
396
- /*
397
- * call-seq:
398
- * document.parent -> node
399
- *
400
- * Obtain the parent node.
401
- */
402
- static VALUE rxml_document_parent_get(VALUE self)
403
- {
404
- xmlDocPtr xdoc;
405
-
406
- Data_Get_Struct(self, xmlDoc, xdoc);
407
-
408
- if (xdoc->parent == NULL)
409
- return (Qnil);
410
-
411
- return rxml_node_wrap(xdoc->parent);
412
- }
413
-
414
- /*
415
- * call-seq:
416
- * document.parent? -> (true|false)
417
- *
418
- * Determine whether there is a parent node.
419
- */
420
- static VALUE rxml_document_parent_q(VALUE self)
421
- {
422
- xmlDocPtr xdoc;
423
-
424
- Data_Get_Struct(self, xmlDoc, xdoc);
425
-
426
- if (xdoc->parent == NULL)
427
- return (Qfalse);
428
- else
429
- return (Qtrue);
430
- }
431
-
432
- /*
433
- * call-seq:
434
- * document.prev -> node
435
- *
436
- * Obtain the previous node.
437
- */
438
- static VALUE rxml_document_prev_get(VALUE self)
439
- {
440
- xmlDocPtr xdoc;
441
-
442
- Data_Get_Struct(self, xmlDoc, xdoc);
443
-
444
- if (xdoc->prev == NULL)
445
- return (Qnil);
446
-
447
- return rxml_node_wrap(xdoc->prev);
448
- }
449
-
450
- /*
451
- * call-seq:
452
- * document.prev? -> (true|false)
453
- *
454
- * Determine whether there is a previous node.
455
- */
456
- static VALUE rxml_document_prev_q(VALUE self)
457
- {
458
- xmlDocPtr xdoc;
459
-
460
- Data_Get_Struct(self, xmlDoc, xdoc);
461
-
462
- if (xdoc->prev == NULL)
463
- return (Qfalse);
464
- else
465
- return (Qtrue);
466
- }
467
-
468
- /*
469
- * call-seq:
470
- * document.root -> node
471
- *
472
- * Obtain the root node.
473
- */
474
- static VALUE rxml_document_root_get(VALUE self)
475
- {
476
- xmlDocPtr xdoc;
477
-
478
- xmlNodePtr root;
479
-
480
- Data_Get_Struct(self, xmlDoc, xdoc);
481
- root = xmlDocGetRootElement(xdoc);
482
-
483
- if (root == NULL)
484
- return (Qnil);
485
-
486
- return rxml_node_wrap(root);
487
- }
488
-
489
- /*
490
- * call-seq:
491
- * document.root = node
492
- *
493
- * Set the root node.
494
- */
495
- static VALUE rxml_document_root_set(VALUE self, VALUE node)
496
- {
497
- xmlDocPtr xdoc;
498
- xmlNodePtr xroot, xnode;
499
-
500
- if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
501
- rb_raise(rb_eTypeError, "must pass an XML::Node type object");
502
-
503
- Data_Get_Struct(self, xmlDoc, xdoc);
504
- Data_Get_Struct(node, xmlNode, xnode);
505
- xroot = xmlDocSetRootElement(xdoc, xnode);
506
- if (xroot == NULL)
507
- return (Qnil);
508
-
509
- return rxml_node_wrap(xroot);
510
- }
511
-
512
- /*
513
- * call-seq:
514
- * document.save(filename) -> int
515
- * document.save(filename, :indent => true, :encoding => 'UTF-8') -> int
516
- *
517
- * Saves a document to a file. You may provide an optional hash table
518
- * to control how the string is generated. Valid options are:
519
- *
520
- * :indent - Specifies if the string should be indented. The default value
521
- * is true. Note that indentation is only added if both :indent is
522
- * true and XML.indent_tree_output is true. If :indent is set to false,
523
- * then both indentation and line feeds are removed from the result.
524
- *
525
- * :encoding - Specifies the output encoding of the string. It
526
- * defaults to the original encoding of the document (see
527
- * #encoding. To override the orginal encoding, use one of the
528
- * XML::Encoding encoding constants. */
529
- static VALUE rxml_document_save(int argc, VALUE *argv, VALUE self)
530
- {
531
- VALUE options = Qnil;
532
- VALUE filename = Qnil;
533
- xmlDocPtr xdoc;
534
- int indent = 1;
535
- const char *xfilename;
536
- const char *xencoding;
537
- int length;
538
-
539
- rb_scan_args(argc, argv, "11", &filename, &options);
540
-
541
- Check_Type(filename, T_STRING);
542
- xfilename = StringValuePtr(filename);
543
-
544
- Data_Get_Struct(self, xmlDoc, xdoc);
545
- xencoding = xdoc->encoding;
546
-
547
- if (!NIL_P(options))
548
- {
549
- VALUE rencoding, rindent;
550
- Check_Type(options, T_HASH);
551
- rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
552
- rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
553
-
554
- if (rindent == Qfalse)
555
- indent = 0;
556
-
557
- if (rencoding != Qnil)
558
- {
559
- xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
560
- if (!xencoding)
561
- rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
562
- }
563
- }
564
-
565
- length = xmlSaveFormatFileEnc(xfilename, xdoc, xencoding, indent);
566
-
567
- if (length == -1)
568
- rxml_raise(&xmlLastError);
569
-
570
- return (INT2NUM(length));
571
- }
572
-
573
- /*
574
- * call-seq:
575
- * document.standalone? -> (true|false)
576
- *
577
- * Determine whether this is a standalone document.
578
- */
579
- static VALUE rxml_document_standalone_q(VALUE self)
580
- {
581
- xmlDocPtr xdoc;
582
-
583
- Data_Get_Struct(self, xmlDoc, xdoc);
584
- if (xdoc->standalone)
585
- return (Qtrue);
586
- else
587
- return (Qfalse);
588
- }
589
-
590
- /*
591
- * call-seq:
592
- * document.to_s -> "string"
593
- * document.to_s(:indent => true, :encoding => 'UTF-8') -> "string"
594
- *
595
- * Converts a document, and all of its children, to a string representation.
596
- * You may provide an optional hash table to control how the string is
597
- * generated. Valid options are:
598
- *
599
- * :indent - Specifies if the string should be indented. The default value
600
- * is true. Note that indentation is only added if both :indent is
601
- * true and XML.indent_tree_output is true. If :indent is set to false,
602
- * then both indentation and line feeds are removed from the result.
603
- *
604
- * :encoding - Specifies the output encoding of the string. It
605
- * defaults to XML::Encoding::UTF8. To change it, use one of the
606
- * XML::Encoding encoding constants. */
607
- static VALUE rxml_document_to_s(int argc, VALUE *argv, VALUE self)
608
- {
609
- VALUE result;
610
- VALUE options = Qnil;
611
- xmlDocPtr xdoc;
612
- int indent = 1;
613
- const char *xencoding = "UTF-8";
614
- xmlChar *buffer;
615
- int length;
616
-
617
- rb_scan_args(argc, argv, "01", &options);
618
-
619
- if (!NIL_P(options))
620
- {
621
- VALUE rencoding, rindent;
622
- Check_Type(options, T_HASH);
623
- rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
624
- rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
625
-
626
- if (rindent == Qfalse)
627
- indent = 0;
628
-
629
- if (rencoding != Qnil)
630
- {
631
- xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
632
- if (!xencoding)
633
- rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
634
- }
635
- }
636
-
637
- Data_Get_Struct(self, xmlDoc, xdoc);
638
- xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, xencoding, indent);
639
-
640
- result = rb_str_new((const char*) buffer, length);
641
- xmlFree(buffer);
642
- return result;
643
- }
644
-
645
- /*
646
- * call-seq:
647
- * document.url -> "url"
648
- *
649
- * Obtain this document's source URL, if any.
650
- */
651
- static VALUE rxml_document_url_get(VALUE self)
652
- {
653
- xmlDocPtr xdoc;
654
-
655
- Data_Get_Struct(self, xmlDoc, xdoc);
656
- if (xdoc->URL == NULL)
657
- return (Qnil);
658
- else
659
- return (rb_str_new2((const char*) xdoc->URL));
660
- }
661
-
662
- /*
663
- * call-seq:
664
- * document.version -> "version"
665
- *
666
- * Obtain the XML version specified by this document.
667
- */
668
- static VALUE rxml_document_version_get(VALUE self)
669
- {
670
- xmlDocPtr xdoc;
671
-
672
- Data_Get_Struct(self, xmlDoc, xdoc);
673
- if (xdoc->version == NULL)
674
- return (Qnil);
675
- else
676
- return (rb_str_new2((const char*) xdoc->version));
677
- }
678
-
679
- /*
680
- * call-seq:
681
- * document.xinclude -> num
682
- *
683
- * Process xinclude directives in this document.
684
- */
685
- static VALUE rxml_document_xinclude(VALUE self)
686
- {
687
- #ifdef LIBXML_XINCLUDE_ENABLED
688
- xmlDocPtr xdoc;
689
-
690
- int ret;
691
-
692
- Data_Get_Struct(self, xmlDoc, xdoc);
693
- ret = xmlXIncludeProcess(xdoc);
694
- if (ret >= 0)
695
- {
696
- return(INT2NUM(ret));
697
- }
698
- else
699
- {
700
- rxml_raise(&xmlLastError);
701
- return Qnil;
702
- }
703
- #else
704
- rb_warn(
705
- "libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
706
- return (Qfalse);
707
- #endif
708
- }
709
-
710
- void LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
711
- {
712
- if (rb_block_given_p())
713
- {
714
- char buff[1024];
715
- snprintf(buff, 1024, msg, ap);
716
- rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
717
- }
718
- else
719
- {
720
- fprintf(stderr, "error -- found validity error: ");
721
- fprintf(stderr, msg, ap);
722
- }
723
- }
724
-
725
- /*
726
- * call-seq:
727
- * document.order_elements!
728
- *
729
- * Call this routine to speed up XPath computation on static documents.
730
- * This stamps all the element nodes with the document order.
731
- */
732
- static VALUE rxml_document_order_elements(VALUE self)
733
- {
734
- xmlDocPtr xdoc;
735
-
736
- Data_Get_Struct(self, xmlDoc, xdoc);
737
- return LONG2FIX(xmlXPathOrderDocElems(xdoc));
738
- }
739
-
740
- /*
741
- * call-seq:
742
- * document.validate_schema(schema) -> (true|false)
743
- *
744
- * Validate this document against the specified XML::Schema.
745
- *
746
- * If a block is provided it is used as an error handler for validaten errors.
747
- * The block is called with two argument, the message and a flag indication
748
- * if the message is an error (true) or a warning (false).
749
- */
750
- static VALUE rxml_document_validate_schema(VALUE self, VALUE schema)
751
- {
752
- xmlSchemaValidCtxtPtr vptr;
753
- xmlDocPtr xdoc;
754
- xmlSchemaPtr xschema;
755
- int is_invalid;
756
-
757
- Data_Get_Struct(self, xmlDoc, xdoc);
758
- Data_Get_Struct(schema, xmlSchema, xschema);
759
-
760
- vptr = xmlSchemaNewValidCtxt(xschema);
761
-
762
- xmlSchemaSetValidErrors(vptr,
763
- (xmlSchemaValidityErrorFunc) LibXML_validity_error,
764
- (xmlSchemaValidityWarningFunc) LibXML_validity_warning, NULL);
765
-
766
- is_invalid = xmlSchemaValidateDoc(vptr, xdoc);
767
- xmlSchemaFreeValidCtxt(vptr);
768
- if (is_invalid)
769
- {
770
- rxml_raise(&xmlLastError);
771
- return Qfalse;
772
- }
773
- else
774
- {
775
- return Qtrue;
776
- }
777
- }
778
-
779
- /*
780
- * call-seq:
781
- * document.validate_schema(relaxng) -> (true|false)
782
- *
783
- * Validate this document against the specified XML::RelaxNG.
784
- *
785
- * If a block is provided it is used as an error handler for validaten errors.
786
- * The block is called with two argument, the message and a flag indication
787
- * if the message is an error (true) or a warning (false).
788
- */
789
- static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng)
790
- {
791
- xmlRelaxNGValidCtxtPtr vptr;
792
- xmlDocPtr xdoc;
793
- xmlRelaxNGPtr xrelaxng;
794
- int is_invalid;
795
-
796
- Data_Get_Struct(self, xmlDoc, xdoc);
797
- Data_Get_Struct(relaxng, xmlRelaxNG, xrelaxng);
798
-
799
- vptr = xmlRelaxNGNewValidCtxt(xrelaxng);
800
-
801
- xmlRelaxNGSetValidErrors(vptr,
802
- (xmlRelaxNGValidityErrorFunc) LibXML_validity_error,
803
- (xmlRelaxNGValidityWarningFunc) LibXML_validity_warning, NULL);
804
-
805
- is_invalid = xmlRelaxNGValidateDoc(vptr, xdoc);
806
- xmlRelaxNGFreeValidCtxt(vptr);
807
- if (is_invalid)
808
- {
809
- rxml_raise(&xmlLastError);
810
- return Qfalse;
811
- }
812
- else
813
- {
814
- return Qtrue;
815
- }
816
- }
817
-
818
- /*
819
- * call-seq:
820
- * document.validate(dtd) -> (true|false)
821
- *
822
- * Validate this document against the specified XML::DTD.
823
- */
824
- static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd)
825
- {
826
- VALUE error = Qnil;
827
- xmlValidCtxt ctxt;
828
- xmlDocPtr xdoc;
829
- xmlDtdPtr xdtd;
830
-
831
- Data_Get_Struct(self, xmlDoc, xdoc);
832
- Data_Get_Struct(dtd, xmlDtd, xdtd);
833
-
834
- ctxt.userData = &error;
835
- ctxt.error = (xmlValidityErrorFunc) LibXML_validity_error;
836
- ctxt.warning = (xmlValidityWarningFunc) LibXML_validity_warning;
837
-
838
- ctxt.nodeNr = 0;
839
- ctxt.nodeTab = NULL;
840
- ctxt.vstateNr = 0;
841
- ctxt.vstateTab = NULL;
842
-
843
- if (xmlValidateDtd(&ctxt, xdoc, xdtd))
844
- {
845
- return (Qtrue);
846
- }
847
- else
848
- {
849
- rxml_raise(&xmlLastError);
850
- return Qfalse;
851
- }
852
- }
853
-
854
-
855
- // Rdoc needs to know
856
- #ifdef RDOC_NEVER_DEFINED
857
- mLibXML = rb_define_module("LibXML");
858
- mXML = rb_define_module_under(mLibXML, "XML");
859
- #endif
860
-
861
- void ruby_init_xml_document(void)
862
- {
863
- cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
864
- rb_define_alloc_func(cXMLDocument, rxml_document_alloc);
865
-
866
- rb_define_method(cXMLDocument, "initialize", rxml_document_initialize, -1);
867
- rb_define_method(cXMLDocument, "child", rxml_document_child_get, 0);
868
- rb_define_method(cXMLDocument, "child?", rxml_document_child_q, 0);
869
- rb_define_method(cXMLDocument, "compression", rxml_document_compression_get, 0);
870
- rb_define_method(cXMLDocument, "compression=", rxml_document_compression_set, 1);
871
- rb_define_method(cXMLDocument, "compression?", rxml_document_compression_q, 0);
872
- rb_define_method(cXMLDocument, "debug", rxml_document_debug, 0);
873
- rb_define_method(cXMLDocument, "encoding", rxml_document_encoding_get, 0);
874
- rb_define_method(cXMLDocument, "encoding=", rxml_document_encoding_set, 1);
875
- rb_define_method(cXMLDocument, "last", rxml_document_last_get, 0);
876
- rb_define_method(cXMLDocument, "last?", rxml_document_last_q, 0);
877
- rb_define_method(cXMLDocument, "next", rxml_document_next_get, 0);
878
- rb_define_method(cXMLDocument, "next?", rxml_document_next_q, 0);
879
- rb_define_method(cXMLDocument, "order_elements!", rxml_document_order_elements, 0);
880
- rb_define_method(cXMLDocument, "parent", rxml_document_parent_get, 0);
881
- rb_define_method(cXMLDocument, "parent?", rxml_document_parent_q, 0);
882
- rb_define_method(cXMLDocument, "prev", rxml_document_prev_get, 0);
883
- rb_define_method(cXMLDocument, "prev?", rxml_document_prev_q, 0);
884
- rb_define_method(cXMLDocument, "root", rxml_document_root_get, 0);
885
- rb_define_method(cXMLDocument, "root=", rxml_document_root_set, 1);
886
- rb_define_method(cXMLDocument, "save", rxml_document_save, -1);
887
- rb_define_method(cXMLDocument, "standalone?", rxml_document_standalone_q, 0);
888
- rb_define_method(cXMLDocument, "to_s", rxml_document_to_s, -1);
889
- rb_define_method(cXMLDocument, "url", rxml_document_url_get, 0);
890
- rb_define_method(cXMLDocument, "version", rxml_document_version_get, 0);
891
- rb_define_method(cXMLDocument, "xinclude", rxml_document_xinclude, 0);
892
- rb_define_method(cXMLDocument, "validate", rxml_document_validate_dtd, 1);
893
- rb_define_method(cXMLDocument, "validate_schema", rxml_document_validate_schema, 1);
894
- rb_define_method(cXMLDocument, "validate_relaxng", rxml_document_validate_relaxng, 1);
895
- }
1
+ /* $Id: ruby_xml_document.c 804 2009-03-05 08:30:56Z 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 read a document from a file:
12
+ *
13
+ * doc = XML::Document.file('my_file')
14
+ *
15
+ * To use a parser to read a document:
16
+ *
17
+ * parser = XML::Parser.file('my_file')
18
+ * doc = parser.parse
19
+ *
20
+ * To create a document from scratch:
21
+ *
22
+ * doc = XML::Document.new()
23
+ * doc.root = XML::Node.new('root_node')
24
+ * doc.root << XML::Node.new('elem1')
25
+ * doc.save(filename, :indent => true, :encoding => 'UTF-8')
26
+ *
27
+ * To write a document to a file:
28
+ *
29
+ * doc = XML::Document.new()
30
+ * doc.root = XML::Node.new('root_node')
31
+ * root = doc.root
32
+ *
33
+ * root << elem1 = XML::Node.new('elem1')
34
+ * elem1['attr1'] = 'val1'
35
+ * elem1['attr2'] = 'val2'
36
+ *
37
+ * root << elem2 = XML::Node.new('elem2')
38
+ * elem2['attr1'] = 'val1'
39
+ * elem2['attr2'] = 'val2'
40
+ *
41
+ * root << elem3 = XML::Node.new('elem3')
42
+ * elem3 << elem4 = XML::Node.new('elem4')
43
+ * elem3 << elem5 = XML::Node.new('elem5')
44
+ *
45
+ * elem5 << elem6 = XML::Node.new('elem6')
46
+ * elem6 << 'Content for element 6'
47
+ *
48
+ * elem3['attr'] = 'baz'
49
+ *
50
+ * doc.save(filename, :indent => true, :encoding => 'UTF-8')
51
+ */
52
+
53
+ #include <stdarg.h>
54
+ #include "ruby_libxml.h"
55
+ #include "ruby_xml_document.h"
56
+
57
+ VALUE cXMLDocument;
58
+
59
+
60
+ void rxml_document_free(xmlDocPtr xdoc)
61
+ {
62
+ xdoc->_private = NULL;
63
+ xmlFreeDoc(xdoc);
64
+ }
65
+
66
+ VALUE rxml_document_wrap(xmlDocPtr xdoc)
67
+ {
68
+ VALUE result;
69
+
70
+ // This node is already wrapped
71
+ if (xdoc->_private != NULL)
72
+ {
73
+ result = (VALUE) xdoc->_private;
74
+ }
75
+ else
76
+ {
77
+ result = Data_Wrap_Struct(cXMLDocument, NULL, rxml_document_free, xdoc);
78
+ xdoc->_private = (void*) result;
79
+ }
80
+
81
+ return result;
82
+ }
83
+
84
+ static void LibXML_validity_warning(void * ctxt, const char * msg, va_list ap)
85
+ {
86
+ if (rb_block_given_p())
87
+ {
88
+ char buff[1024];
89
+ snprintf(buff, 1024, msg, ap);
90
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qfalse));
91
+ }
92
+ else
93
+ {
94
+ fprintf(stderr, "warning -- found validity error: ");
95
+ fprintf(stderr, msg, ap);
96
+ }
97
+ }
98
+
99
+ /*
100
+ * call-seq:
101
+ * XML::Document.alloc(xml_version = 1.0) -> document
102
+ *
103
+ * Alocates a new XML::Document, optionally specifying the
104
+ * XML version.
105
+ */
106
+ static VALUE rxml_document_alloc(VALUE klass)
107
+ {
108
+ return Data_Wrap_Struct(klass, NULL, rxml_document_free, NULL);
109
+ }
110
+
111
+ /*
112
+ * call-seq:
113
+ * XML::Document.initialize(xml_version = 1.0) -> document
114
+ *
115
+ * Initializes a new XML::Document, optionally specifying the
116
+ * XML version.
117
+ */
118
+ static VALUE rxml_document_initialize(int argc, VALUE *argv, VALUE self)
119
+ {
120
+ xmlDocPtr xdoc;
121
+ VALUE xmlver;
122
+
123
+ switch (argc)
124
+ {
125
+ case 0:
126
+ xmlver = rb_str_new2("1.0");
127
+ break;
128
+ case 1:
129
+ rb_scan_args(argc, argv, "01", &xmlver);
130
+ break;
131
+ default:
132
+ rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
133
+ }
134
+
135
+ Check_Type(xmlver, T_STRING);
136
+ xdoc = xmlNewDoc((xmlChar*) StringValuePtr(xmlver));
137
+ xdoc->_private = (void*) self;
138
+ DATA_PTR(self) = xdoc;
139
+
140
+ return self;
141
+ }
142
+
143
+ /*
144
+ * call-seq:
145
+ * document.compression -> num
146
+ *
147
+ * Obtain this document's compression mode identifier.
148
+ */
149
+ static VALUE rxml_document_compression_get(VALUE self)
150
+ {
151
+ #ifdef HAVE_ZLIB_H
152
+ xmlDocPtr xdoc;
153
+
154
+ int compmode;
155
+ Data_Get_Struct(self, xmlDoc, xdoc);
156
+
157
+ compmode = xmlGetDocCompressMode(xdoc);
158
+ if (compmode == -1)
159
+ return(Qnil);
160
+ else
161
+ return(INT2NUM(compmode));
162
+ #else
163
+ rb_warn("libxml not compiled with zlib support");
164
+ return (Qfalse);
165
+ #endif
166
+ }
167
+
168
+ /*
169
+ * call-seq:
170
+ * document.compression = num
171
+ *
172
+ * Set this document's compression mode.
173
+ */
174
+ static VALUE rxml_document_compression_set(VALUE self, VALUE num)
175
+ {
176
+ #ifdef HAVE_ZLIB_H
177
+ xmlDocPtr xdoc;
178
+
179
+ int compmode;
180
+ Check_Type(num, T_FIXNUM);
181
+ Data_Get_Struct(self, xmlDoc, xdoc);
182
+
183
+ if (xdoc == NULL)
184
+ {
185
+ return(Qnil);
186
+ }
187
+ else
188
+ {
189
+ xmlSetDocCompressMode(xdoc, NUM2INT(num));
190
+
191
+ compmode = xmlGetDocCompressMode(xdoc);
192
+ if (compmode == -1)
193
+ return(Qnil);
194
+ else
195
+ return(INT2NUM(compmode));
196
+ }
197
+ #else
198
+ rb_warn("libxml compiled without zlib support");
199
+ return (Qfalse);
200
+ #endif
201
+ }
202
+
203
+ /*
204
+ * call-seq:
205
+ * document.compression? -> (true|false)
206
+ *
207
+ * Determine whether this document is compressed.
208
+ */
209
+ static VALUE rxml_document_compression_q(VALUE self)
210
+ {
211
+ #ifdef HAVE_ZLIB_H
212
+ xmlDocPtr xdoc;
213
+
214
+ Data_Get_Struct(self, xmlDoc, xdoc);
215
+
216
+ if (xdoc->compression != -1)
217
+ return(Qtrue);
218
+ else
219
+ return(Qfalse);
220
+ #else
221
+ rb_warn("libxml compiled without zlib support");
222
+ return (Qfalse);
223
+ #endif
224
+ }
225
+
226
+ /*
227
+ * call-seq:
228
+ * document.child -> node
229
+ *
230
+ * Get this document's child node.
231
+ */
232
+ static VALUE rxml_document_child_get(VALUE self)
233
+ {
234
+ xmlDocPtr xdoc;
235
+ Data_Get_Struct(self, xmlDoc, xdoc);
236
+
237
+ if (xdoc->children == NULL)
238
+ return (Qnil);
239
+
240
+ return rxml_node_wrap(xdoc->children);
241
+ }
242
+
243
+ /*
244
+ * call-seq:
245
+ * document.child? -> (true|false)
246
+ *
247
+ * Determine whether this document has a child node.
248
+ */
249
+ static VALUE rxml_document_child_q(VALUE self)
250
+ {
251
+ xmlDocPtr xdoc;
252
+ Data_Get_Struct(self, xmlDoc, xdoc);
253
+
254
+ if (xdoc->children == NULL)
255
+ return (Qfalse);
256
+ else
257
+ return (Qtrue);
258
+ }
259
+
260
+
261
+ /*
262
+ * call-seq:
263
+ * node.debug -> true|false
264
+ *
265
+ * Print libxml debugging information to stdout.
266
+ * Requires that libxml was compiled with debugging enabled.
267
+ */
268
+ static VALUE rxml_document_debug(VALUE self)
269
+ {
270
+ #ifdef LIBXML_DEBUG_ENABLED
271
+ xmlDocPtr xdoc;
272
+ Data_Get_Struct(self, xmlDoc, xdoc);
273
+ xmlDebugDumpDocument(NULL, xdoc);
274
+ return Qtrue;
275
+ #else
276
+ rb_warn("libxml was compiled without debugging support.")
277
+ return Qfalse;
278
+ #endif
279
+ }
280
+
281
+ /*
282
+ * call-seq:
283
+ * document.encoding -> XML::Encoding::UTF_8
284
+ *
285
+ * Obtain the encoding specified by this document.
286
+ */
287
+ static VALUE rxml_document_encoding_get(VALUE self)
288
+ {
289
+ xmlDocPtr xdoc;
290
+ const char *xencoding;
291
+ Data_Get_Struct(self, xmlDoc, xdoc);
292
+
293
+ xencoding = (const char*)xdoc->encoding;
294
+ return INT2NUM(xmlParseCharEncoding(xencoding));
295
+ }
296
+
297
+ /*
298
+ * call-seq:
299
+ * document.encoding = XML::Encoding::UTF_8
300
+ *
301
+ * Set the encoding for this document.
302
+ */
303
+ static VALUE rxml_document_encoding_set(VALUE self, VALUE encoding)
304
+ {
305
+ xmlDocPtr xdoc;
306
+ const char* xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(encoding));
307
+
308
+ Data_Get_Struct(self, xmlDoc, xdoc);
309
+
310
+ if (xdoc->encoding != NULL)
311
+ xmlFree((xmlChar *) xdoc->encoding);
312
+
313
+ xdoc->encoding = xmlStrdup((xmlChar *)xencoding);
314
+ return self;
315
+ }
316
+
317
+ /*
318
+ * call-seq:
319
+ * document.last -> node
320
+ *
321
+ * Obtain the last node.
322
+ */
323
+ static VALUE rxml_document_last_get(VALUE self)
324
+ {
325
+ xmlDocPtr xdoc;
326
+
327
+ Data_Get_Struct(self, xmlDoc, xdoc);
328
+
329
+ if (xdoc->last == NULL)
330
+ return (Qnil);
331
+
332
+ return rxml_node_wrap(xdoc->last);
333
+ }
334
+
335
+ /*
336
+ * call-seq:
337
+ * document.last? -> (true|false)
338
+ *
339
+ * Determine whether there is a last node.
340
+ */
341
+ static VALUE rxml_document_last_q(VALUE self)
342
+ {
343
+ xmlDocPtr xdoc;
344
+
345
+ Data_Get_Struct(self, xmlDoc, xdoc);
346
+
347
+ if (xdoc->last == NULL)
348
+ return (Qfalse);
349
+ else
350
+ return (Qtrue);
351
+ }
352
+
353
+ /*
354
+ * call-seq:
355
+ * document.next -> node
356
+ *
357
+ * Obtain the next node.
358
+ */
359
+ static VALUE rxml_document_next_get(VALUE self)
360
+ {
361
+ xmlDocPtr xdoc;
362
+
363
+ Data_Get_Struct(self, xmlDoc, xdoc);
364
+
365
+ if (xdoc->next == NULL)
366
+ return (Qnil);
367
+
368
+ return rxml_node_wrap(xdoc->next);
369
+ }
370
+
371
+ /*
372
+ * call-seq:
373
+ * document.next? -> (true|false)
374
+ *
375
+ * Determine whether there is a next node.
376
+ */
377
+ static VALUE rxml_document_next_q(VALUE self)
378
+ {
379
+ xmlDocPtr xdoc;
380
+
381
+ Data_Get_Struct(self, xmlDoc, xdoc);
382
+
383
+ if (xdoc->next == NULL)
384
+ return (Qfalse);
385
+ else
386
+ return (Qtrue);
387
+ }
388
+
389
+ /*
390
+ * call-seq:
391
+ * node.type -> num
392
+ *
393
+ * Obtain this node's type identifier.
394
+ */
395
+ static VALUE rxml_document_node_type(VALUE self)
396
+ {
397
+ xmlNodePtr xnode;
398
+ Data_Get_Struct(self, xmlNode, xnode);
399
+ return (INT2NUM(xnode->type));
400
+ }
401
+
402
+ /*
403
+ * call-seq:
404
+ * document.parent -> node
405
+ *
406
+ * Obtain the parent node.
407
+ */
408
+ static VALUE rxml_document_parent_get(VALUE self)
409
+ {
410
+ xmlDocPtr xdoc;
411
+
412
+ Data_Get_Struct(self, xmlDoc, xdoc);
413
+
414
+ if (xdoc->parent == NULL)
415
+ return (Qnil);
416
+
417
+ return rxml_node_wrap(xdoc->parent);
418
+ }
419
+
420
+ /*
421
+ * call-seq:
422
+ * document.parent? -> (true|false)
423
+ *
424
+ * Determine whether there is a parent node.
425
+ */
426
+ static VALUE rxml_document_parent_q(VALUE self)
427
+ {
428
+ xmlDocPtr xdoc;
429
+
430
+ Data_Get_Struct(self, xmlDoc, xdoc);
431
+
432
+ if (xdoc->parent == NULL)
433
+ return (Qfalse);
434
+ else
435
+ return (Qtrue);
436
+ }
437
+
438
+ /*
439
+ * call-seq:
440
+ * document.prev -> node
441
+ *
442
+ * Obtain the previous node.
443
+ */
444
+ static VALUE rxml_document_prev_get(VALUE self)
445
+ {
446
+ xmlDocPtr xdoc;
447
+
448
+ Data_Get_Struct(self, xmlDoc, xdoc);
449
+
450
+ if (xdoc->prev == NULL)
451
+ return (Qnil);
452
+
453
+ return rxml_node_wrap(xdoc->prev);
454
+ }
455
+
456
+ /*
457
+ * call-seq:
458
+ * document.prev? -> (true|false)
459
+ *
460
+ * Determine whether there is a previous node.
461
+ */
462
+ static VALUE rxml_document_prev_q(VALUE self)
463
+ {
464
+ xmlDocPtr xdoc;
465
+
466
+ Data_Get_Struct(self, xmlDoc, xdoc);
467
+
468
+ if (xdoc->prev == NULL)
469
+ return (Qfalse);
470
+ else
471
+ return (Qtrue);
472
+ }
473
+
474
+ /*
475
+ * call-seq:
476
+ * document.root -> node
477
+ *
478
+ * Obtain the root node.
479
+ */
480
+ static VALUE rxml_document_root_get(VALUE self)
481
+ {
482
+ xmlDocPtr xdoc;
483
+
484
+ xmlNodePtr root;
485
+
486
+ Data_Get_Struct(self, xmlDoc, xdoc);
487
+ root = xmlDocGetRootElement(xdoc);
488
+
489
+ if (root == NULL)
490
+ return (Qnil);
491
+
492
+ return rxml_node_wrap(root);
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * document.root = node
498
+ *
499
+ * Set the root node.
500
+ */
501
+ static VALUE rxml_document_root_set(VALUE self, VALUE node)
502
+ {
503
+ xmlDocPtr xdoc;
504
+ xmlNodePtr xroot, xnode;
505
+
506
+ if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
507
+ rb_raise(rb_eTypeError, "must pass an XML::Node type object");
508
+
509
+ Data_Get_Struct(self, xmlDoc, xdoc);
510
+ Data_Get_Struct(node, xmlNode, xnode);
511
+
512
+ xroot = xmlDocSetRootElement(xdoc, xnode);
513
+ if (xroot == NULL)
514
+ return (Qnil);
515
+
516
+ return rxml_node_wrap(xroot);
517
+ }
518
+
519
+ /*
520
+ * call-seq:
521
+ * document.save(filename) -> int
522
+ * document.save(filename, :indent => true, :encoding => 'UTF-8') -> int
523
+ *
524
+ * Saves a document to a file. You may provide an optional hash table
525
+ * to control how the string is generated. Valid options are:
526
+ *
527
+ * :indent - Specifies if the string should be indented. The default value
528
+ * is true. Note that indentation is only added if both :indent is
529
+ * true and XML.indent_tree_output is true. If :indent is set to false,
530
+ * then both indentation and line feeds are removed from the result.
531
+ *
532
+ * :encoding - Specifies the output encoding of the string. It
533
+ * defaults to the original encoding of the document (see
534
+ * #encoding. To override the orginal encoding, use one of the
535
+ * XML::Encoding encoding constants. */
536
+ static VALUE rxml_document_save(int argc, VALUE *argv, VALUE self)
537
+ {
538
+ VALUE options = Qnil;
539
+ VALUE filename = Qnil;
540
+ xmlDocPtr xdoc;
541
+ int indent = 1;
542
+ const char *xfilename;
543
+ const char *xencoding;
544
+ int length;
545
+
546
+ rb_scan_args(argc, argv, "11", &filename, &options);
547
+
548
+ Check_Type(filename, T_STRING);
549
+ xfilename = StringValuePtr(filename);
550
+
551
+ Data_Get_Struct(self, xmlDoc, xdoc);
552
+ xencoding = xdoc->encoding;
553
+
554
+ if (!NIL_P(options))
555
+ {
556
+ VALUE rencoding, rindent;
557
+ Check_Type(options, T_HASH);
558
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
559
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
560
+
561
+ if (rindent == Qfalse)
562
+ indent = 0;
563
+
564
+ if (rencoding != Qnil)
565
+ {
566
+ xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
567
+ if (!xencoding)
568
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
569
+ }
570
+ }
571
+
572
+ length = xmlSaveFormatFileEnc(xfilename, xdoc, xencoding, indent);
573
+
574
+ if (length == -1)
575
+ rxml_raise(&xmlLastError);
576
+
577
+ return (INT2NUM(length));
578
+ }
579
+
580
+ /*
581
+ * call-seq:
582
+ * document.standalone? -> (true|false)
583
+ *
584
+ * Determine whether this is a standalone document.
585
+ */
586
+ static VALUE rxml_document_standalone_q(VALUE self)
587
+ {
588
+ xmlDocPtr xdoc;
589
+
590
+ Data_Get_Struct(self, xmlDoc, xdoc);
591
+ if (xdoc->standalone)
592
+ return (Qtrue);
593
+ else
594
+ return (Qfalse);
595
+ }
596
+
597
+ /*
598
+ * call-seq:
599
+ * document.to_s -> "string"
600
+ * document.to_s(:indent => true, :encoding => 'UTF-8') -> "string"
601
+ *
602
+ * Converts a document, and all of its children, to a string representation.
603
+ * You may provide an optional hash table to control how the string is
604
+ * generated. Valid options are:
605
+ *
606
+ * :indent - Specifies if the string should be indented. The default value
607
+ * is true. Note that indentation is only added if both :indent is
608
+ * true and XML.indent_tree_output is true. If :indent is set to false,
609
+ * then both indentation and line feeds are removed from the result.
610
+ *
611
+ * :encoding - Specifies the output encoding of the string. It
612
+ * defaults to XML::Encoding::UTF8. To change it, use one of the
613
+ * XML::Encoding encoding constants. */
614
+ static VALUE rxml_document_to_s(int argc, VALUE *argv, VALUE self)
615
+ {
616
+ VALUE result;
617
+ VALUE options = Qnil;
618
+ xmlDocPtr xdoc;
619
+ int indent = 1;
620
+ const char *xencoding = "UTF-8";
621
+ xmlChar *buffer;
622
+ int length;
623
+
624
+ rb_scan_args(argc, argv, "01", &options);
625
+
626
+ if (!NIL_P(options))
627
+ {
628
+ VALUE rencoding, rindent;
629
+ Check_Type(options, T_HASH);
630
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
631
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
632
+
633
+ if (rindent == Qfalse)
634
+ indent = 0;
635
+
636
+ if (rencoding != Qnil)
637
+ {
638
+ xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
639
+ if (!xencoding)
640
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
641
+ }
642
+ }
643
+
644
+ Data_Get_Struct(self, xmlDoc, xdoc);
645
+ xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, xencoding, indent);
646
+
647
+ result = rb_str_new((const char*) buffer, length);
648
+ xmlFree(buffer);
649
+ return result;
650
+ }
651
+
652
+ /*
653
+ * call-seq:
654
+ * document.url -> "url"
655
+ *
656
+ * Obtain this document's source URL, if any.
657
+ */
658
+ static VALUE rxml_document_url_get(VALUE self)
659
+ {
660
+ xmlDocPtr xdoc;
661
+
662
+ Data_Get_Struct(self, xmlDoc, xdoc);
663
+ if (xdoc->URL == NULL)
664
+ return (Qnil);
665
+ else
666
+ return (rb_str_new2((const char*) xdoc->URL));
667
+ }
668
+
669
+ /*
670
+ * call-seq:
671
+ * document.version -> "version"
672
+ *
673
+ * Obtain the XML version specified by this document.
674
+ */
675
+ static VALUE rxml_document_version_get(VALUE self)
676
+ {
677
+ xmlDocPtr xdoc;
678
+
679
+ Data_Get_Struct(self, xmlDoc, xdoc);
680
+ if (xdoc->version == NULL)
681
+ return (Qnil);
682
+ else
683
+ return (rb_str_new2((const char*) xdoc->version));
684
+ }
685
+
686
+ /*
687
+ * call-seq:
688
+ * document.xhtml? -> (true|false)
689
+ *
690
+ * Determine whether this is an XHTML document.
691
+ */
692
+ static VALUE rxml_document_xhtml_q(VALUE self)
693
+ {
694
+ xmlDocPtr xdoc;
695
+ xmlDtdPtr xdtd;
696
+ Data_Get_Struct(self, xmlDoc, xdoc);
697
+ xdtd = xmlGetIntSubset(xdoc);
698
+ if (xdtd != NULL && xmlIsXHTML(xdtd->SystemID, xdtd->ExternalID) > 0)
699
+ return (Qtrue);
700
+ else
701
+ return (Qfalse);
702
+ }
703
+
704
+ /*
705
+ * call-seq:
706
+ * document.xinclude -> num
707
+ *
708
+ * Process xinclude directives in this document.
709
+ */
710
+ static VALUE rxml_document_xinclude(VALUE self)
711
+ {
712
+ #ifdef LIBXML_XINCLUDE_ENABLED
713
+ xmlDocPtr xdoc;
714
+
715
+ int ret;
716
+
717
+ Data_Get_Struct(self, xmlDoc, xdoc);
718
+ ret = xmlXIncludeProcess(xdoc);
719
+ if (ret >= 0)
720
+ {
721
+ return(INT2NUM(ret));
722
+ }
723
+ else
724
+ {
725
+ rxml_raise(&xmlLastError);
726
+ return Qnil;
727
+ }
728
+ #else
729
+ rb_warn(
730
+ "libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
731
+ return (Qfalse);
732
+ #endif
733
+ }
734
+
735
+ void LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
736
+ {
737
+ if (rb_block_given_p())
738
+ {
739
+ char buff[1024];
740
+ snprintf(buff, 1024, msg, ap);
741
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
742
+ }
743
+ else
744
+ {
745
+ fprintf(stderr, "error -- found validity error: ");
746
+ fprintf(stderr, msg, ap);
747
+ }
748
+ }
749
+
750
+ /*
751
+ * call-seq:
752
+ * document.order_elements!
753
+ *
754
+ * Call this routine to speed up XPath computation on static documents.
755
+ * This stamps all the element nodes with the document order.
756
+ */
757
+ static VALUE rxml_document_order_elements(VALUE self)
758
+ {
759
+ xmlDocPtr xdoc;
760
+
761
+ Data_Get_Struct(self, xmlDoc, xdoc);
762
+ return LONG2FIX(xmlXPathOrderDocElems(xdoc));
763
+ }
764
+
765
+ /*
766
+ * call-seq:
767
+ * document.validate_schema(schema) -> (true|false)
768
+ *
769
+ * Validate this document against the specified XML::Schema.
770
+ *
771
+ * If a block is provided it is used as an error handler for validaten errors.
772
+ * The block is called with two argument, the message and a flag indication
773
+ * if the message is an error (true) or a warning (false).
774
+ */
775
+ static VALUE rxml_document_validate_schema(VALUE self, VALUE schema)
776
+ {
777
+ xmlSchemaValidCtxtPtr vptr;
778
+ xmlDocPtr xdoc;
779
+ xmlSchemaPtr xschema;
780
+ int is_invalid;
781
+
782
+ Data_Get_Struct(self, xmlDoc, xdoc);
783
+ Data_Get_Struct(schema, xmlSchema, xschema);
784
+
785
+ vptr = xmlSchemaNewValidCtxt(xschema);
786
+
787
+ xmlSchemaSetValidErrors(vptr,
788
+ (xmlSchemaValidityErrorFunc) LibXML_validity_error,
789
+ (xmlSchemaValidityWarningFunc) LibXML_validity_warning, NULL);
790
+
791
+ is_invalid = xmlSchemaValidateDoc(vptr, xdoc);
792
+ xmlSchemaFreeValidCtxt(vptr);
793
+ if (is_invalid)
794
+ {
795
+ rxml_raise(&xmlLastError);
796
+ return Qfalse;
797
+ }
798
+ else
799
+ {
800
+ return Qtrue;
801
+ }
802
+ }
803
+
804
+ /*
805
+ * call-seq:
806
+ * document.validate_schema(relaxng) -> (true|false)
807
+ *
808
+ * Validate this document against the specified XML::RelaxNG.
809
+ *
810
+ * If a block is provided it is used as an error handler for validaten errors.
811
+ * The block is called with two argument, the message and a flag indication
812
+ * if the message is an error (true) or a warning (false).
813
+ */
814
+ static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng)
815
+ {
816
+ xmlRelaxNGValidCtxtPtr vptr;
817
+ xmlDocPtr xdoc;
818
+ xmlRelaxNGPtr xrelaxng;
819
+ int is_invalid;
820
+
821
+ Data_Get_Struct(self, xmlDoc, xdoc);
822
+ Data_Get_Struct(relaxng, xmlRelaxNG, xrelaxng);
823
+
824
+ vptr = xmlRelaxNGNewValidCtxt(xrelaxng);
825
+
826
+ xmlRelaxNGSetValidErrors(vptr,
827
+ (xmlRelaxNGValidityErrorFunc) LibXML_validity_error,
828
+ (xmlRelaxNGValidityWarningFunc) LibXML_validity_warning, NULL);
829
+
830
+ is_invalid = xmlRelaxNGValidateDoc(vptr, xdoc);
831
+ xmlRelaxNGFreeValidCtxt(vptr);
832
+ if (is_invalid)
833
+ {
834
+ rxml_raise(&xmlLastError);
835
+ return Qfalse;
836
+ }
837
+ else
838
+ {
839
+ return Qtrue;
840
+ }
841
+ }
842
+
843
+ /*
844
+ * call-seq:
845
+ * document.validate(dtd) -> (true|false)
846
+ *
847
+ * Validate this document against the specified XML::DTD.
848
+ */
849
+ static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd)
850
+ {
851
+ VALUE error = Qnil;
852
+ xmlValidCtxt ctxt;
853
+ xmlDocPtr xdoc;
854
+ xmlDtdPtr xdtd;
855
+
856
+ Data_Get_Struct(self, xmlDoc, xdoc);
857
+ Data_Get_Struct(dtd, xmlDtd, xdtd);
858
+
859
+ ctxt.userData = &error;
860
+ ctxt.error = (xmlValidityErrorFunc) LibXML_validity_error;
861
+ ctxt.warning = (xmlValidityWarningFunc) LibXML_validity_warning;
862
+
863
+ ctxt.nodeNr = 0;
864
+ ctxt.nodeTab = NULL;
865
+ ctxt.vstateNr = 0;
866
+ ctxt.vstateTab = NULL;
867
+
868
+ if (xmlValidateDtd(&ctxt, xdoc, xdtd))
869
+ {
870
+ return (Qtrue);
871
+ }
872
+ else
873
+ {
874
+ rxml_raise(&xmlLastError);
875
+ return Qfalse;
876
+ }
877
+ }
878
+
879
+ void rxml_init_document(void)
880
+ {
881
+ cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
882
+ rb_define_alloc_func(cXMLDocument, rxml_document_alloc);
883
+
884
+ rb_define_method(cXMLDocument, "initialize", rxml_document_initialize, -1);
885
+ rb_define_method(cXMLDocument, "child", rxml_document_child_get, 0);
886
+ rb_define_method(cXMLDocument, "child?", rxml_document_child_q, 0);
887
+ rb_define_method(cXMLDocument, "compression", rxml_document_compression_get, 0);
888
+ rb_define_method(cXMLDocument, "compression=", rxml_document_compression_set, 1);
889
+ rb_define_method(cXMLDocument, "compression?", rxml_document_compression_q, 0);
890
+ rb_define_method(cXMLDocument, "debug", rxml_document_debug, 0);
891
+ rb_define_method(cXMLDocument, "encoding", rxml_document_encoding_get, 0);
892
+ rb_define_method(cXMLDocument, "encoding=", rxml_document_encoding_set, 1);
893
+ rb_define_method(cXMLDocument, "last", rxml_document_last_get, 0);
894
+ rb_define_method(cXMLDocument, "last?", rxml_document_last_q, 0);
895
+ rb_define_method(cXMLDocument, "next", rxml_document_next_get, 0);
896
+ rb_define_method(cXMLDocument, "next?", rxml_document_next_q, 0);
897
+ rb_define_method(cXMLDocument, "node_type", rxml_document_node_type, 0);
898
+ rb_define_method(cXMLDocument, "order_elements!", rxml_document_order_elements, 0);
899
+ rb_define_method(cXMLDocument, "parent", rxml_document_parent_get, 0);
900
+ rb_define_method(cXMLDocument, "parent?", rxml_document_parent_q, 0);
901
+ rb_define_method(cXMLDocument, "prev", rxml_document_prev_get, 0);
902
+ rb_define_method(cXMLDocument, "prev?", rxml_document_prev_q, 0);
903
+ rb_define_method(cXMLDocument, "root", rxml_document_root_get, 0);
904
+ rb_define_method(cXMLDocument, "root=", rxml_document_root_set, 1);
905
+ rb_define_method(cXMLDocument, "save", rxml_document_save, -1);
906
+ rb_define_method(cXMLDocument, "standalone?", rxml_document_standalone_q, 0);
907
+ rb_define_method(cXMLDocument, "to_s", rxml_document_to_s, -1);
908
+ rb_define_method(cXMLDocument, "url", rxml_document_url_get, 0);
909
+ rb_define_method(cXMLDocument, "version", rxml_document_version_get, 0);
910
+ rb_define_method(cXMLDocument, "xhtml?", rxml_document_xhtml_q, 0);
911
+ rb_define_method(cXMLDocument, "xinclude", rxml_document_xinclude, 0);
912
+ rb_define_method(cXMLDocument, "validate", rxml_document_validate_dtd, 1);
913
+ rb_define_method(cXMLDocument, "validate_schema", rxml_document_validate_schema, 1);
914
+ rb_define_method(cXMLDocument, "validate_relaxng", rxml_document_validate_relaxng, 1);
915
+ }