libxml-ruby 0.9.9-x86-mswin32-60 → 1.0.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.0.0 / 2009-03-05 Charlie Savage
2
+
3
+ * OS X (Charlie Savage). Update bindings to support the default installed
4
+ version of libxml2 (2.6.16) on OS X 10.5 and the latest version available
5
+ via MacPorts.
6
+
1
7
  == 0.9.9 / 2009-03-05 Charlie Savage
2
8
 
3
9
  * Ruby 1.9.1 support (Charlie Savage). libxml-ruby now compiles and runs on either
@@ -37,6 +43,8 @@
37
43
 
38
44
  * Bug fix - Fix output escaping on attributes nodes (Joe Khoobyar).
39
45
 
46
+ * Bug fix - Make sure IO objects are not garbage collected when used
47
+ as parser sources (Charlie Savage).
40
48
 
41
49
  == 0.9.8 / 2009-1-24 Charlie Savage
42
50
 
@@ -114,14 +114,6 @@ need libxml2.
114
114
  EOL
115
115
  end
116
116
 
117
- unless have_func('xmlDocFormatDump')
118
- crash('Your version of libxml2 is too old. Please upgrade.')
119
- end
120
-
121
- unless have_func('docbCreateFileParserCtxt')
122
- crash('Need docbCreateFileParserCtxt')
123
- end
124
-
125
117
  # For FreeBSD add /usr/local/include
126
118
  $INCFLAGS << " -I/usr/local/include"
127
119
 
data/ext/libxml/libxml.c CHANGED
@@ -1,76 +1,76 @@
1
- #include "ruby_libxml.h"
2
-
3
- #if RUBY_INTERN_H
4
- #include <ruby/util.h>
5
- #else
6
- #include <util.h>
7
- #endif
8
-
9
- VALUE mLibXML;
10
-
11
- static void rxml_init_memory(void)
12
- {
13
- xmlGcMemSetup(
14
- (xmlFreeFunc)ruby_xfree,
15
- (xmlMallocFunc)ruby_xmalloc,
16
- (xmlMallocFunc)ruby_xmalloc,
17
- (xmlReallocFunc)ruby_xrealloc,
18
- (xmlStrdupFunc)ruby_strdup
19
- );
20
- }
21
-
22
- #if defined(_WIN32)
23
- __declspec(dllexport)
24
- #endif
25
- void Init_libxml_ruby(void)
26
- {
27
- /* The libxml gem provides Ruby language bindings for GNOME's Libxml2
28
- * XML toolkit. To get started you may:
29
- *
30
- * require 'xml'
31
- * document = XML::Document.new
32
- *
33
- * However, when creating an application or library you plan to
34
- * redistribute, it is best to not add the LibXML module to the global
35
- * namespace, in which case you can either write your code like this:
36
- *
37
- * require 'libxml'
38
- * document = LibXML::XML::Document.new
39
- *
40
- * Refer to the README file to get started and the LICENSE file for
41
- * copyright and distribution information.
42
- */
43
- mLibXML = rb_define_module("LibXML");
44
-
45
- rxml_init_memory();
46
- rxml_init_xml();
47
- rxml_init_io();
48
- rxml_init_error();
49
- rxml_init_encoding();
50
- rxml_init_parser();
51
- rxml_init_parser_context();
52
- rxml_init_parser_options();
53
- rxml_init_node();
54
- rxml_init_attributes();
55
- rxml_init_attr();
56
- rxml_init_attr_decl();
57
- rxml_init_document();
58
- rxml_init_namespaces();
59
- rxml_init_namespace();
60
- rxml_init_sax_parser();
61
- rxml_init_sax2_handler();
62
- rxml_init_xinclude();
63
- rxml_init_xpath();
64
- rxml_init_xpath_object();
65
- rxml_init_xpath_context();
66
- rxml_init_xpath_expression();
67
- rxml_init_xpointer();
68
- rxml_init_html_parser();
69
- rxml_init_html_parser_options();
70
- rxml_init_html_parser_context();
71
- rxml_init_input_callbacks();
72
- rxml_init_dtd();
73
- rxml_init_schema();
74
- rxml_init_relaxng();
75
- rxml_init_reader();
76
- }
1
+ #include "ruby_libxml.h"
2
+
3
+ #if RUBY_INTERN_H
4
+ #include <ruby/util.h>
5
+ #else
6
+ #include <util.h>
7
+ #endif
8
+
9
+ VALUE mLibXML;
10
+
11
+ static void rxml_init_memory(void)
12
+ {
13
+ xmlGcMemSetup(
14
+ (xmlFreeFunc)ruby_xfree,
15
+ (xmlMallocFunc)ruby_xmalloc,
16
+ (xmlMallocFunc)ruby_xmalloc,
17
+ (xmlReallocFunc)ruby_xrealloc,
18
+ (xmlStrdupFunc)ruby_strdup
19
+ );
20
+ }
21
+
22
+ #if defined(_WIN32)
23
+ __declspec(dllexport)
24
+ #endif
25
+ void Init_libxml_ruby(void)
26
+ {
27
+ /* The libxml gem provides Ruby language bindings for GNOME's Libxml2
28
+ * XML toolkit. To get started you may:
29
+ *
30
+ * require 'xml'
31
+ * document = XML::Document.new
32
+ *
33
+ * However, when creating an application or library you plan to
34
+ * redistribute, it is best to not add the LibXML module to the global
35
+ * namespace, in which case you can either write your code like this:
36
+ *
37
+ * require 'libxml'
38
+ * document = LibXML::XML::Document.new
39
+ *
40
+ * Refer to the README file to get started and the LICENSE file for
41
+ * copyright and distribution information.
42
+ */
43
+ mLibXML = rb_define_module("LibXML");
44
+
45
+ rxml_init_memory();
46
+ rxml_init_xml();
47
+ rxml_init_io();
48
+ rxml_init_error();
49
+ rxml_init_encoding();
50
+ rxml_init_parser();
51
+ rxml_init_parser_context();
52
+ rxml_init_parser_options();
53
+ rxml_init_node();
54
+ rxml_init_attributes();
55
+ rxml_init_attr();
56
+ rxml_init_attr_decl();
57
+ rxml_init_document();
58
+ rxml_init_namespaces();
59
+ rxml_init_namespace();
60
+ rxml_init_sax_parser();
61
+ rxml_init_sax2_handler();
62
+ rxml_init_xinclude();
63
+ rxml_init_xpath();
64
+ rxml_init_xpath_object();
65
+ rxml_init_xpath_context();
66
+ rxml_init_xpath_expression();
67
+ rxml_init_xpointer();
68
+ rxml_init_html_parser();
69
+ rxml_init_html_parser_options();
70
+ rxml_init_html_parser_context();
71
+ rxml_init_input_callbacks();
72
+ rxml_init_dtd();
73
+ rxml_init_schema();
74
+ rxml_init_relaxng();
75
+ rxml_init_reader();
76
+ }
@@ -1,93 +1,93 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- #ifndef __RUBY_LIBXML_H__
4
- #define __RUBY_LIBXML_H__
5
-
6
- #include <ruby.h>
7
- #include <libxml/parser.h>
8
- #include <libxml/parserInternals.h>
9
- #include <libxml/debugXML.h>
10
- #include <libxml/xmlversion.h>
11
- #include <libxml/xmlmemory.h>
12
- #include <libxml/xpath.h>
13
- #include <libxml/valid.h>
14
- #include <libxml/catalog.h>
15
- #include <libxml/HTMLparser.h>
16
- #include <libxml/xmlreader.h>
17
-
18
- /* Needed for Ruby 1.8.5 */
19
- #ifndef RARRAY_LEN
20
- #define RARRAY_LEN(s) (RARRAY(s)->len)
21
- #endif
22
-
23
- /* Needed for Ruby 1.8.5 */
24
- #ifndef RARRAY_PTR
25
- #define RARRAY_PTR(s) (RARRAY(s)->ptr)
26
- #endif
27
-
28
- /* Needed for Ruby 1.8.5 */
29
- #ifndef RSTRING_LEN
30
- #define RSTRING_LEN(s) (RSTRING(s)->len)
31
- #endif
32
-
33
- /* Needed for Ruby 1.8.5 */
34
- #ifndef RSTRING_PTR
35
- #define RSTRING_PTR(s) (RSTRING(s)->ptr)
36
- #endif
37
-
38
- /* Needed prior to Ruby 1.9.1 */
39
- #ifndef RHASH_TBL
40
- #define RHASH_TBL(s) (RHASH(s)->tbl)
41
- #endif
42
-
43
- // not in Ruby 1.9
44
- #ifndef GetWriteFile
45
- #define GetWriteFile(fp) rb_io_stdio_file(fp)
46
- #define OpenFile rb_io_t
47
- #endif
48
-
49
- #ifdef LIBXML_DEBUG_ENABLED
50
- #include <libxml/xpathInternals.h>
51
- #endif
52
- #ifdef LIBXML_XINCLUDE_ENABLED
53
- #include <libxml/xinclude.h>
54
- #endif
55
- #ifdef LIBXML_XPTR_ENABLED
56
- #include <libxml/xpointer.h>
57
- #endif
58
-
59
- #include "ruby_xml_version.h"
60
- #include "ruby_xml.h"
61
- #include "ruby_xml_io.h"
62
- #include "ruby_xml_error.h"
63
- #include "ruby_xml_encoding.h"
64
- #include "ruby_xml_attributes.h"
65
- #include "ruby_xml_attr.h"
66
- #include "ruby_xml_attr_decl.h"
67
- #include "ruby_xml_document.h"
68
- #include "ruby_xml_node.h"
69
- #include "ruby_xml_namespace.h"
70
- #include "ruby_xml_namespaces.h"
71
- #include "ruby_xml_parser.h"
72
- #include "ruby_xml_parser_options.h"
73
- #include "ruby_xml_parser_context.h"
74
- #include "ruby_xml_html_parser.h"
75
- #include "ruby_xml_html_parser_options.h"
76
- #include "ruby_xml_html_parser_context.h"
77
- #include "ruby_xml_reader.h"
78
- #include "ruby_xml_sax2_handler.h"
79
- #include "ruby_xml_sax_parser.h"
80
- #include "ruby_xml_xinclude.h"
81
- #include "ruby_xml_xpath.h"
82
- #include "ruby_xml_xpath_expression.h"
83
- #include "ruby_xml_xpath_context.h"
84
- #include "ruby_xml_xpath_object.h"
85
- #include "ruby_xml_xpointer.h"
86
- #include "ruby_xml_input_cbg.h"
87
- #include "ruby_xml_dtd.h"
88
- #include "ruby_xml_schema.h"
89
- #include "ruby_xml_relaxng.h"
90
-
91
- extern VALUE mLibXML;
92
-
93
- #endif
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RUBY_LIBXML_H__
4
+ #define __RUBY_LIBXML_H__
5
+
6
+ #include <ruby.h>
7
+ #include <libxml/parser.h>
8
+ #include <libxml/parserInternals.h>
9
+ #include <libxml/debugXML.h>
10
+ #include <libxml/xmlversion.h>
11
+ #include <libxml/xmlmemory.h>
12
+ #include <libxml/xpath.h>
13
+ #include <libxml/valid.h>
14
+ #include <libxml/catalog.h>
15
+ #include <libxml/HTMLparser.h>
16
+ #include <libxml/xmlreader.h>
17
+
18
+ /* Needed for Ruby 1.8.5 */
19
+ #ifndef RARRAY_LEN
20
+ #define RARRAY_LEN(s) (RARRAY(s)->len)
21
+ #endif
22
+
23
+ /* Needed for Ruby 1.8.5 */
24
+ #ifndef RARRAY_PTR
25
+ #define RARRAY_PTR(s) (RARRAY(s)->ptr)
26
+ #endif
27
+
28
+ /* Needed for Ruby 1.8.5 */
29
+ #ifndef RSTRING_LEN
30
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
31
+ #endif
32
+
33
+ /* Needed for Ruby 1.8.5 */
34
+ #ifndef RSTRING_PTR
35
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
36
+ #endif
37
+
38
+ /* Needed prior to Ruby 1.9.1 */
39
+ #ifndef RHASH_TBL
40
+ #define RHASH_TBL(s) (RHASH(s)->tbl)
41
+ #endif
42
+
43
+ // not in Ruby 1.9
44
+ #ifndef GetWriteFile
45
+ #define GetWriteFile(fp) rb_io_stdio_file(fp)
46
+ #define OpenFile rb_io_t
47
+ #endif
48
+
49
+ #ifdef LIBXML_DEBUG_ENABLED
50
+ #include <libxml/xpathInternals.h>
51
+ #endif
52
+ #ifdef LIBXML_XINCLUDE_ENABLED
53
+ #include <libxml/xinclude.h>
54
+ #endif
55
+ #ifdef LIBXML_XPTR_ENABLED
56
+ #include <libxml/xpointer.h>
57
+ #endif
58
+
59
+ #include "ruby_xml_version.h"
60
+ #include "ruby_xml.h"
61
+ #include "ruby_xml_io.h"
62
+ #include "ruby_xml_error.h"
63
+ #include "ruby_xml_encoding.h"
64
+ #include "ruby_xml_attributes.h"
65
+ #include "ruby_xml_attr.h"
66
+ #include "ruby_xml_attr_decl.h"
67
+ #include "ruby_xml_document.h"
68
+ #include "ruby_xml_node.h"
69
+ #include "ruby_xml_namespace.h"
70
+ #include "ruby_xml_namespaces.h"
71
+ #include "ruby_xml_parser.h"
72
+ #include "ruby_xml_parser_options.h"
73
+ #include "ruby_xml_parser_context.h"
74
+ #include "ruby_xml_html_parser.h"
75
+ #include "ruby_xml_html_parser_options.h"
76
+ #include "ruby_xml_html_parser_context.h"
77
+ #include "ruby_xml_reader.h"
78
+ #include "ruby_xml_sax2_handler.h"
79
+ #include "ruby_xml_sax_parser.h"
80
+ #include "ruby_xml_xinclude.h"
81
+ #include "ruby_xml_xpath.h"
82
+ #include "ruby_xml_xpath_expression.h"
83
+ #include "ruby_xml_xpath_context.h"
84
+ #include "ruby_xml_xpath_object.h"
85
+ #include "ruby_xml_xpointer.h"
86
+ #include "ruby_xml_input_cbg.h"
87
+ #include "ruby_xml_dtd.h"
88
+ #include "ruby_xml_schema.h"
89
+ #include "ruby_xml_relaxng.h"
90
+
91
+ extern VALUE mLibXML;
92
+
93
+ #endif
@@ -1,915 +1,915 @@
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
- }
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
+ }