libxml-ruby 1.1.2-x86-mswin32-60 → 1.1.3-x86-mswin32-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,7 +23,7 @@ void rxml_attr_decl_mark(xmlAttributePtr xattribute)
23
23
  return;
24
24
  }
25
25
 
26
- rxml_node_mark_common((xmlNodePtr) xattribute);
26
+ rxml_node_mark((xmlNodePtr) xattribute);
27
27
  }
28
28
 
29
29
  VALUE rxml_attr_decl_wrap(xmlAttributePtr xattribute)
@@ -36,7 +36,7 @@ VALUE cXMLAttributes;
36
36
 
37
37
  void rxml_attributes_mark(xmlNodePtr xnode)
38
38
  {
39
- rxml_node_mark_common(xnode);
39
+ rxml_node_mark(xnode);
40
40
  }
41
41
 
42
42
  /*
@@ -80,7 +80,7 @@ static VALUE rxml_attributes_get_attribute(VALUE self, VALUE name)
80
80
  xmlNodePtr xnode;
81
81
  xmlAttrPtr xattr;
82
82
 
83
- name = check_string_or_symbol(name);
83
+ name = rb_obj_as_string(name);
84
84
 
85
85
  Data_Get_Struct(self, xmlNode, xnode);
86
86
 
@@ -114,7 +114,7 @@ static VALUE rxml_attributes_get_attribute_ns(VALUE self, VALUE namespace,
114
114
  xmlNodePtr xnode;
115
115
  xmlAttrPtr xattr;
116
116
 
117
- name = check_string_or_symbol(name);
117
+ name = rb_obj_as_string(name);
118
118
 
119
119
  Data_Get_Struct(self, xmlNode, xnode);
120
120
 
@@ -1,86 +1,86 @@
1
- #include "ruby_libxml.h"
2
- #include <string.h>
3
- #include <libxml/xmlIO.h>
4
-
5
- /*
6
- int xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc,
7
- xmlInputOpenCallback openFunc,
8
- xmlInputReadCallback readFunc,
9
- xmlInputCloseCallback closeFunc);
10
-
11
-
12
- int (*xmlInputMatchCallback) (char const *filename);
13
- void* (*xmlInputOpenCallback) (char const *filename);
14
- int (*xmlInputReadCallback) (void *context,
15
- char *buffer,
16
- int len);
17
- int (*xmlInputCloseCallback) (void *context);
18
- */
19
-
20
- typedef struct deb_doc_context
21
- {
22
- char *buffer;
23
- char *bpos;
24
- int remaining;
25
- } deb_doc_context;
26
-
27
- int deb_Match(char const *filename)
28
- {
29
- fprintf(stderr, "deb_Match: %s\n", filename);
30
- if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "deb://", 6))
31
- {
32
- return (1);
33
- }
34
- return (0);
35
- }
36
-
37
- void* deb_Open(char const *filename)
38
- {
39
- deb_doc_context *deb_doc;
40
- VALUE res;
41
-
42
- deb_doc = (deb_doc_context*) malloc(sizeof(deb_doc_context));
43
-
44
- res = rb_funcall(rb_funcall(rb_mKernel, rb_intern("const_get"), 1,
45
- rb_str_new2("DEBSystem")), rb_intern("document_query"), 1, rb_str_new2(
46
- filename));
47
- deb_doc->buffer = strdup(StringValuePtr(res));
48
- //deb_doc->buffer = strdup("<serepes>serepes</serepes>");
49
-
50
- deb_doc->bpos = deb_doc->buffer;
51
- deb_doc->remaining = strlen(deb_doc->buffer);
52
- return deb_doc;
53
- }
54
-
55
- int deb_Read(void *context, char *buffer, int len)
56
- {
57
- deb_doc_context *deb_doc;
58
- int ret_len;
59
- deb_doc = (deb_doc_context*) context;
60
-
61
- if (len >= deb_doc->remaining)
62
- {
63
- ret_len = deb_doc->remaining;
64
- }
65
- else
66
- {
67
- ret_len = len;
68
- }
69
- deb_doc->remaining -= ret_len;
70
- strncpy(buffer, deb_doc->bpos, ret_len);
71
- deb_doc->bpos += ret_len;
72
-
73
- return ret_len;
74
- }
75
-
76
- int deb_Close(void *context)
77
- {
78
- free(((deb_doc_context*) context)->buffer);
79
- free(context);
80
- return 1;
81
- }
82
-
83
- void deb_register_cbg()
84
- {
85
- xmlRegisterInputCallbacks(deb_Match, deb_Open, deb_Read, deb_Close);
86
- }
1
+ #include "ruby_libxml.h"
2
+ #include <string.h>
3
+ #include <libxml/xmlIO.h>
4
+
5
+ /*
6
+ int xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc,
7
+ xmlInputOpenCallback openFunc,
8
+ xmlInputReadCallback readFunc,
9
+ xmlInputCloseCallback closeFunc);
10
+
11
+
12
+ int (*xmlInputMatchCallback) (char const *filename);
13
+ void* (*xmlInputOpenCallback) (char const *filename);
14
+ int (*xmlInputReadCallback) (void *context,
15
+ char *buffer,
16
+ int len);
17
+ int (*xmlInputCloseCallback) (void *context);
18
+ */
19
+
20
+ typedef struct deb_doc_context
21
+ {
22
+ char *buffer;
23
+ char *bpos;
24
+ int remaining;
25
+ } deb_doc_context;
26
+
27
+ int deb_Match(char const *filename)
28
+ {
29
+ fprintf(stderr, "deb_Match: %s\n", filename);
30
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "deb://", 6))
31
+ {
32
+ return (1);
33
+ }
34
+ return (0);
35
+ }
36
+
37
+ void* deb_Open(char const *filename)
38
+ {
39
+ deb_doc_context *deb_doc;
40
+ VALUE res;
41
+
42
+ deb_doc = (deb_doc_context*) malloc(sizeof(deb_doc_context));
43
+
44
+ res = rb_funcall(rb_funcall(rb_mKernel, rb_intern("const_get"), 1,
45
+ rb_str_new2("DEBSystem")), rb_intern("document_query"), 1, rb_str_new2(
46
+ filename));
47
+ deb_doc->buffer = strdup(StringValuePtr(res));
48
+ //deb_doc->buffer = strdup("<serepes>serepes</serepes>");
49
+
50
+ deb_doc->bpos = deb_doc->buffer;
51
+ deb_doc->remaining = strlen(deb_doc->buffer);
52
+ return deb_doc;
53
+ }
54
+
55
+ int deb_Read(void *context, char *buffer, int len)
56
+ {
57
+ deb_doc_context *deb_doc;
58
+ int ret_len;
59
+ deb_doc = (deb_doc_context*) context;
60
+
61
+ if (len >= deb_doc->remaining)
62
+ {
63
+ ret_len = deb_doc->remaining;
64
+ }
65
+ else
66
+ {
67
+ ret_len = len;
68
+ }
69
+ deb_doc->remaining -= ret_len;
70
+ strncpy(buffer, deb_doc->bpos, ret_len);
71
+ deb_doc->bpos += ret_len;
72
+
73
+ return ret_len;
74
+ }
75
+
76
+ int deb_Close(void *context)
77
+ {
78
+ free(((deb_doc_context*) context)->buffer);
79
+ free(context);
80
+ return 1;
81
+ }
82
+
83
+ void deb_register_cbg()
84
+ {
85
+ xmlRegisterInputCallbacks(deb_Match, deb_Open, deb_Read, deb_Close);
86
+ }
@@ -1,915 +1,936 @@
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 854 2009-03-22 04:27:13Z 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.import(node) -> XML::Node
320
+ *
321
+ * Creates a copy of the node that can be inserted into the
322
+ * current document.
323
+ */
324
+ static VALUE rxml_document_import(VALUE self, VALUE node)
325
+ {
326
+ xmlDocPtr xdoc;
327
+ xmlNodePtr xnode, xresult;
328
+
329
+ Data_Get_Struct(self, xmlDoc, xdoc);
330
+ Data_Get_Struct(node, xmlNode, xnode);
331
+
332
+ xresult = xmlDocCopyNode(xnode, xdoc, 1);
333
+
334
+ if (xresult == NULL)
335
+ rxml_raise(&xmlLastError);
336
+
337
+ return rxml_node_wrap(xresult);
338
+ }
339
+
340
+ /*
341
+ * call-seq:
342
+ * document.last -> node
343
+ *
344
+ * Obtain the last node.
345
+ */
346
+ static VALUE rxml_document_last_get(VALUE self)
347
+ {
348
+ xmlDocPtr xdoc;
349
+
350
+ Data_Get_Struct(self, xmlDoc, xdoc);
351
+
352
+ if (xdoc->last == NULL)
353
+ return (Qnil);
354
+
355
+ return rxml_node_wrap(xdoc->last);
356
+ }
357
+
358
+ /*
359
+ * call-seq:
360
+ * document.last? -> (true|false)
361
+ *
362
+ * Determine whether there is a last node.
363
+ */
364
+ static VALUE rxml_document_last_q(VALUE self)
365
+ {
366
+ xmlDocPtr xdoc;
367
+
368
+ Data_Get_Struct(self, xmlDoc, xdoc);
369
+
370
+ if (xdoc->last == NULL)
371
+ return (Qfalse);
372
+ else
373
+ return (Qtrue);
374
+ }
375
+
376
+ /*
377
+ * call-seq:
378
+ * document.next -> node
379
+ *
380
+ * Obtain the next node.
381
+ */
382
+ static VALUE rxml_document_next_get(VALUE self)
383
+ {
384
+ xmlDocPtr xdoc;
385
+
386
+ Data_Get_Struct(self, xmlDoc, xdoc);
387
+
388
+ if (xdoc->next == NULL)
389
+ return (Qnil);
390
+
391
+ return rxml_node_wrap(xdoc->next);
392
+ }
393
+
394
+ /*
395
+ * call-seq:
396
+ * document.next? -> (true|false)
397
+ *
398
+ * Determine whether there is a next node.
399
+ */
400
+ static VALUE rxml_document_next_q(VALUE self)
401
+ {
402
+ xmlDocPtr xdoc;
403
+
404
+ Data_Get_Struct(self, xmlDoc, xdoc);
405
+
406
+ if (xdoc->next == NULL)
407
+ return (Qfalse);
408
+ else
409
+ return (Qtrue);
410
+ }
411
+
412
+ /*
413
+ * call-seq:
414
+ * node.type -> num
415
+ *
416
+ * Obtain this node's type identifier.
417
+ */
418
+ static VALUE rxml_document_node_type(VALUE self)
419
+ {
420
+ xmlNodePtr xnode;
421
+ Data_Get_Struct(self, xmlNode, xnode);
422
+ return (INT2NUM(xnode->type));
423
+ }
424
+
425
+ /*
426
+ * call-seq:
427
+ * document.parent -> node
428
+ *
429
+ * Obtain the parent node.
430
+ */
431
+ static VALUE rxml_document_parent_get(VALUE self)
432
+ {
433
+ xmlDocPtr xdoc;
434
+
435
+ Data_Get_Struct(self, xmlDoc, xdoc);
436
+
437
+ if (xdoc->parent == NULL)
438
+ return (Qnil);
439
+
440
+ return rxml_node_wrap(xdoc->parent);
441
+ }
442
+
443
+ /*
444
+ * call-seq:
445
+ * document.parent? -> (true|false)
446
+ *
447
+ * Determine whether there is a parent node.
448
+ */
449
+ static VALUE rxml_document_parent_q(VALUE self)
450
+ {
451
+ xmlDocPtr xdoc;
452
+
453
+ Data_Get_Struct(self, xmlDoc, xdoc);
454
+
455
+ if (xdoc->parent == NULL)
456
+ return (Qfalse);
457
+ else
458
+ return (Qtrue);
459
+ }
460
+
461
+ /*
462
+ * call-seq:
463
+ * document.prev -> node
464
+ *
465
+ * Obtain the previous node.
466
+ */
467
+ static VALUE rxml_document_prev_get(VALUE self)
468
+ {
469
+ xmlDocPtr xdoc;
470
+
471
+ Data_Get_Struct(self, xmlDoc, xdoc);
472
+
473
+ if (xdoc->prev == NULL)
474
+ return (Qnil);
475
+
476
+ return rxml_node_wrap(xdoc->prev);
477
+ }
478
+
479
+ /*
480
+ * call-seq:
481
+ * document.prev? -> (true|false)
482
+ *
483
+ * Determine whether there is a previous node.
484
+ */
485
+ static VALUE rxml_document_prev_q(VALUE self)
486
+ {
487
+ xmlDocPtr xdoc;
488
+
489
+ Data_Get_Struct(self, xmlDoc, xdoc);
490
+
491
+ if (xdoc->prev == NULL)
492
+ return (Qfalse);
493
+ else
494
+ return (Qtrue);
495
+ }
496
+
497
+ /*
498
+ * call-seq:
499
+ * document.root -> node
500
+ *
501
+ * Obtain the root node.
502
+ */
503
+ static VALUE rxml_document_root_get(VALUE self)
504
+ {
505
+ xmlDocPtr xdoc;
506
+
507
+ xmlNodePtr root;
508
+
509
+ Data_Get_Struct(self, xmlDoc, xdoc);
510
+ root = xmlDocGetRootElement(xdoc);
511
+
512
+ if (root == NULL)
513
+ return (Qnil);
514
+
515
+ return rxml_node_wrap(root);
516
+ }
517
+
518
+ /*
519
+ * call-seq:
520
+ * document.root = node
521
+ *
522
+ * Set the root node.
523
+ */
524
+ static VALUE rxml_document_root_set(VALUE self, VALUE node)
525
+ {
526
+ xmlDocPtr xdoc;
527
+ xmlNodePtr xroot, xnode;
528
+
529
+ if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
530
+ rb_raise(rb_eTypeError, "must pass an XML::Node type object");
531
+
532
+ Data_Get_Struct(self, xmlDoc, xdoc);
533
+ Data_Get_Struct(node, xmlNode, xnode);
534
+
535
+ xroot = xmlDocSetRootElement(xdoc, xnode);
536
+ return node;
537
+ }
538
+
539
+ /*
540
+ * call-seq:
541
+ * document.save(filename) -> int
542
+ * document.save(filename, :indent => true, :encoding => 'UTF-8') -> int
543
+ *
544
+ * Saves a document to a file. You may provide an optional hash table
545
+ * to control how the string is generated. Valid options are:
546
+ *
547
+ * :indent - Specifies if the string should be indented. The default value
548
+ * is true. Note that indentation is only added if both :indent is
549
+ * true and XML.indent_tree_output is true. If :indent is set to false,
550
+ * then both indentation and line feeds are removed from the result.
551
+ *
552
+ * :encoding - Specifies the output encoding of the string. It
553
+ * defaults to the original encoding of the document (see
554
+ * #encoding. To override the orginal encoding, use one of the
555
+ * XML::Encoding encoding constants. */
556
+ static VALUE rxml_document_save(int argc, VALUE *argv, VALUE self)
557
+ {
558
+ VALUE options = Qnil;
559
+ VALUE filename = Qnil;
560
+ xmlDocPtr xdoc;
561
+ int indent = 1;
562
+ const char *xfilename;
563
+ const char *xencoding;
564
+ int length;
565
+
566
+ rb_scan_args(argc, argv, "11", &filename, &options);
567
+
568
+ Check_Type(filename, T_STRING);
569
+ xfilename = StringValuePtr(filename);
570
+
571
+ Data_Get_Struct(self, xmlDoc, xdoc);
572
+ xencoding = xdoc->encoding;
573
+
574
+ if (!NIL_P(options))
575
+ {
576
+ VALUE rencoding, rindent;
577
+ Check_Type(options, T_HASH);
578
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
579
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
580
+
581
+ if (rindent == Qfalse)
582
+ indent = 0;
583
+
584
+ if (rencoding != Qnil)
585
+ {
586
+ xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
587
+ if (!xencoding)
588
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
589
+ }
590
+ }
591
+
592
+ length = xmlSaveFormatFileEnc(xfilename, xdoc, xencoding, indent);
593
+
594
+ if (length == -1)
595
+ rxml_raise(&xmlLastError);
596
+
597
+ return (INT2NUM(length));
598
+ }
599
+
600
+ /*
601
+ * call-seq:
602
+ * document.standalone? -> (true|false)
603
+ *
604
+ * Determine whether this is a standalone document.
605
+ */
606
+ static VALUE rxml_document_standalone_q(VALUE self)
607
+ {
608
+ xmlDocPtr xdoc;
609
+
610
+ Data_Get_Struct(self, xmlDoc, xdoc);
611
+ if (xdoc->standalone)
612
+ return (Qtrue);
613
+ else
614
+ return (Qfalse);
615
+ }
616
+
617
+ /*
618
+ * call-seq:
619
+ * document.to_s -> "string"
620
+ * document.to_s(:indent => true, :encoding => 'UTF-8') -> "string"
621
+ *
622
+ * Converts a document, and all of its children, to a string representation.
623
+ * You may provide an optional hash table to control how the string is
624
+ * generated. Valid options are:
625
+ *
626
+ * :indent - Specifies if the string should be indented. The default value
627
+ * is true. Note that indentation is only added if both :indent is
628
+ * true and XML.indent_tree_output is true. If :indent is set to false,
629
+ * then both indentation and line feeds are removed from the result.
630
+ *
631
+ * :encoding - Specifies the output encoding of the string. It
632
+ * defaults to XML::Encoding::UTF8. To change it, use one of the
633
+ * XML::Encoding encoding constants. */
634
+ static VALUE rxml_document_to_s(int argc, VALUE *argv, VALUE self)
635
+ {
636
+ VALUE result;
637
+ VALUE options = Qnil;
638
+ xmlDocPtr xdoc;
639
+ int indent = 1;
640
+ const char *xencoding = "UTF-8";
641
+ xmlChar *buffer;
642
+ int length;
643
+
644
+ rb_scan_args(argc, argv, "01", &options);
645
+
646
+ if (!NIL_P(options))
647
+ {
648
+ VALUE rencoding, rindent;
649
+ Check_Type(options, T_HASH);
650
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
651
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
652
+
653
+ if (rindent == Qfalse)
654
+ indent = 0;
655
+
656
+ if (rencoding != Qnil)
657
+ {
658
+ xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
659
+ if (!xencoding)
660
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
661
+ }
662
+ }
663
+
664
+ Data_Get_Struct(self, xmlDoc, xdoc);
665
+ xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, xencoding, indent);
666
+
667
+ result = rb_str_new((const char*) buffer, length);
668
+ xmlFree(buffer);
669
+ return result;
670
+ }
671
+
672
+ /*
673
+ * call-seq:
674
+ * document.url -> "url"
675
+ *
676
+ * Obtain this document's source URL, if any.
677
+ */
678
+ static VALUE rxml_document_url_get(VALUE self)
679
+ {
680
+ xmlDocPtr xdoc;
681
+
682
+ Data_Get_Struct(self, xmlDoc, xdoc);
683
+ if (xdoc->URL == NULL)
684
+ return (Qnil);
685
+ else
686
+ return (rb_str_new2((const char*) xdoc->URL));
687
+ }
688
+
689
+ /*
690
+ * call-seq:
691
+ * document.version -> "version"
692
+ *
693
+ * Obtain the XML version specified by this document.
694
+ */
695
+ static VALUE rxml_document_version_get(VALUE self)
696
+ {
697
+ xmlDocPtr xdoc;
698
+
699
+ Data_Get_Struct(self, xmlDoc, xdoc);
700
+ if (xdoc->version == NULL)
701
+ return (Qnil);
702
+ else
703
+ return (rb_str_new2((const char*) xdoc->version));
704
+ }
705
+
706
+ /*
707
+ * call-seq:
708
+ * document.xhtml? -> (true|false)
709
+ *
710
+ * Determine whether this is an XHTML document.
711
+ */
712
+ static VALUE rxml_document_xhtml_q(VALUE self)
713
+ {
714
+ xmlDocPtr xdoc;
715
+ xmlDtdPtr xdtd;
716
+ Data_Get_Struct(self, xmlDoc, xdoc);
717
+ xdtd = xmlGetIntSubset(xdoc);
718
+ if (xdtd != NULL && xmlIsXHTML(xdtd->SystemID, xdtd->ExternalID) > 0)
719
+ return (Qtrue);
720
+ else
721
+ return (Qfalse);
722
+ }
723
+
724
+ /*
725
+ * call-seq:
726
+ * document.xinclude -> num
727
+ *
728
+ * Process xinclude directives in this document.
729
+ */
730
+ static VALUE rxml_document_xinclude(VALUE self)
731
+ {
732
+ #ifdef LIBXML_XINCLUDE_ENABLED
733
+ xmlDocPtr xdoc;
734
+
735
+ int ret;
736
+
737
+ Data_Get_Struct(self, xmlDoc, xdoc);
738
+ ret = xmlXIncludeProcess(xdoc);
739
+ if (ret >= 0)
740
+ {
741
+ return(INT2NUM(ret));
742
+ }
743
+ else
744
+ {
745
+ rxml_raise(&xmlLastError);
746
+ return Qnil;
747
+ }
748
+ #else
749
+ rb_warn(
750
+ "libxml was compiled without XInclude support. Please recompile libxml and ruby-libxml");
751
+ return (Qfalse);
752
+ #endif
753
+ }
754
+
755
+ void LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
756
+ {
757
+ if (rb_block_given_p())
758
+ {
759
+ char buff[1024];
760
+ snprintf(buff, 1024, msg, ap);
761
+ rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
762
+ }
763
+ else
764
+ {
765
+ fprintf(stderr, "error -- found validity error: ");
766
+ fprintf(stderr, msg, ap);
767
+ }
768
+ }
769
+
770
+ /*
771
+ * call-seq:
772
+ * document.order_elements!
773
+ *
774
+ * Call this routine to speed up XPath computation on static documents.
775
+ * This stamps all the element nodes with the document order.
776
+ */
777
+ static VALUE rxml_document_order_elements(VALUE self)
778
+ {
779
+ xmlDocPtr xdoc;
780
+
781
+ Data_Get_Struct(self, xmlDoc, xdoc);
782
+ return LONG2FIX(xmlXPathOrderDocElems(xdoc));
783
+ }
784
+
785
+ /*
786
+ * call-seq:
787
+ * document.validate_schema(schema) -> (true|false)
788
+ *
789
+ * Validate this document against the specified XML::Schema.
790
+ *
791
+ * If a block is provided it is used as an error handler for validaten errors.
792
+ * The block is called with two argument, the message and a flag indication
793
+ * if the message is an error (true) or a warning (false).
794
+ */
795
+ static VALUE rxml_document_validate_schema(VALUE self, VALUE schema)
796
+ {
797
+ xmlSchemaValidCtxtPtr vptr;
798
+ xmlDocPtr xdoc;
799
+ xmlSchemaPtr xschema;
800
+ int is_invalid;
801
+
802
+ Data_Get_Struct(self, xmlDoc, xdoc);
803
+ Data_Get_Struct(schema, xmlSchema, xschema);
804
+
805
+ vptr = xmlSchemaNewValidCtxt(xschema);
806
+
807
+ xmlSchemaSetValidErrors(vptr,
808
+ (xmlSchemaValidityErrorFunc) LibXML_validity_error,
809
+ (xmlSchemaValidityWarningFunc) LibXML_validity_warning, NULL);
810
+
811
+ is_invalid = xmlSchemaValidateDoc(vptr, xdoc);
812
+ xmlSchemaFreeValidCtxt(vptr);
813
+ if (is_invalid)
814
+ {
815
+ rxml_raise(&xmlLastError);
816
+ return Qfalse;
817
+ }
818
+ else
819
+ {
820
+ return Qtrue;
821
+ }
822
+ }
823
+
824
+ /*
825
+ * call-seq:
826
+ * document.validate_schema(relaxng) -> (true|false)
827
+ *
828
+ * Validate this document against the specified XML::RelaxNG.
829
+ *
830
+ * If a block is provided it is used as an error handler for validaten errors.
831
+ * The block is called with two argument, the message and a flag indication
832
+ * if the message is an error (true) or a warning (false).
833
+ */
834
+ static VALUE rxml_document_validate_relaxng(VALUE self, VALUE relaxng)
835
+ {
836
+ xmlRelaxNGValidCtxtPtr vptr;
837
+ xmlDocPtr xdoc;
838
+ xmlRelaxNGPtr xrelaxng;
839
+ int is_invalid;
840
+
841
+ Data_Get_Struct(self, xmlDoc, xdoc);
842
+ Data_Get_Struct(relaxng, xmlRelaxNG, xrelaxng);
843
+
844
+ vptr = xmlRelaxNGNewValidCtxt(xrelaxng);
845
+
846
+ xmlRelaxNGSetValidErrors(vptr,
847
+ (xmlRelaxNGValidityErrorFunc) LibXML_validity_error,
848
+ (xmlRelaxNGValidityWarningFunc) LibXML_validity_warning, NULL);
849
+
850
+ is_invalid = xmlRelaxNGValidateDoc(vptr, xdoc);
851
+ xmlRelaxNGFreeValidCtxt(vptr);
852
+ if (is_invalid)
853
+ {
854
+ rxml_raise(&xmlLastError);
855
+ return Qfalse;
856
+ }
857
+ else
858
+ {
859
+ return Qtrue;
860
+ }
861
+ }
862
+
863
+ /*
864
+ * call-seq:
865
+ * document.validate(dtd) -> (true|false)
866
+ *
867
+ * Validate this document against the specified XML::DTD.
868
+ */
869
+ static VALUE rxml_document_validate_dtd(VALUE self, VALUE dtd)
870
+ {
871
+ VALUE error = Qnil;
872
+ xmlValidCtxt ctxt;
873
+ xmlDocPtr xdoc;
874
+ xmlDtdPtr xdtd;
875
+
876
+ Data_Get_Struct(self, xmlDoc, xdoc);
877
+ Data_Get_Struct(dtd, xmlDtd, xdtd);
878
+
879
+ ctxt.userData = &error;
880
+ ctxt.error = (xmlValidityErrorFunc) LibXML_validity_error;
881
+ ctxt.warning = (xmlValidityWarningFunc) LibXML_validity_warning;
882
+
883
+ ctxt.nodeNr = 0;
884
+ ctxt.nodeTab = NULL;
885
+ ctxt.vstateNr = 0;
886
+ ctxt.vstateTab = NULL;
887
+
888
+ if (xmlValidateDtd(&ctxt, xdoc, xdtd))
889
+ {
890
+ return (Qtrue);
891
+ }
892
+ else
893
+ {
894
+ rxml_raise(&xmlLastError);
895
+ return Qfalse;
896
+ }
897
+ }
898
+
899
+ void rxml_init_document(void)
900
+ {
901
+ cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
902
+ rb_define_alloc_func(cXMLDocument, rxml_document_alloc);
903
+
904
+ rb_define_method(cXMLDocument, "initialize", rxml_document_initialize, -1);
905
+ rb_define_method(cXMLDocument, "child", rxml_document_child_get, 0);
906
+ rb_define_method(cXMLDocument, "child?", rxml_document_child_q, 0);
907
+ rb_define_method(cXMLDocument, "compression", rxml_document_compression_get, 0);
908
+ rb_define_method(cXMLDocument, "compression=", rxml_document_compression_set, 1);
909
+ rb_define_method(cXMLDocument, "compression?", rxml_document_compression_q, 0);
910
+ rb_define_method(cXMLDocument, "debug", rxml_document_debug, 0);
911
+ rb_define_method(cXMLDocument, "encoding", rxml_document_encoding_get, 0);
912
+ rb_define_method(cXMLDocument, "encoding=", rxml_document_encoding_set, 1);
913
+ rb_define_method(cXMLDocument, "import", rxml_document_import, 1);
914
+ rb_define_method(cXMLDocument, "last", rxml_document_last_get, 0);
915
+ rb_define_method(cXMLDocument, "last?", rxml_document_last_q, 0);
916
+ rb_define_method(cXMLDocument, "next", rxml_document_next_get, 0);
917
+ rb_define_method(cXMLDocument, "next?", rxml_document_next_q, 0);
918
+ rb_define_method(cXMLDocument, "node_type", rxml_document_node_type, 0);
919
+ rb_define_method(cXMLDocument, "order_elements!", rxml_document_order_elements, 0);
920
+ rb_define_method(cXMLDocument, "parent", rxml_document_parent_get, 0);
921
+ rb_define_method(cXMLDocument, "parent?", rxml_document_parent_q, 0);
922
+ rb_define_method(cXMLDocument, "prev", rxml_document_prev_get, 0);
923
+ rb_define_method(cXMLDocument, "prev?", rxml_document_prev_q, 0);
924
+ rb_define_method(cXMLDocument, "root", rxml_document_root_get, 0);
925
+ rb_define_method(cXMLDocument, "root=", rxml_document_root_set, 1);
926
+ rb_define_method(cXMLDocument, "save", rxml_document_save, -1);
927
+ rb_define_method(cXMLDocument, "standalone?", rxml_document_standalone_q, 0);
928
+ rb_define_method(cXMLDocument, "to_s", rxml_document_to_s, -1);
929
+ rb_define_method(cXMLDocument, "url", rxml_document_url_get, 0);
930
+ rb_define_method(cXMLDocument, "version", rxml_document_version_get, 0);
931
+ rb_define_method(cXMLDocument, "xhtml?", rxml_document_xhtml_q, 0);
932
+ rb_define_method(cXMLDocument, "xinclude", rxml_document_xinclude, 0);
933
+ rb_define_method(cXMLDocument, "validate", rxml_document_validate_dtd, 1);
934
+ rb_define_method(cXMLDocument, "validate_schema", rxml_document_validate_schema, 1);
935
+ rb_define_method(cXMLDocument, "validate_relaxng", rxml_document_validate_relaxng, 1);
936
+ }