libxml-ruby 2.7.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +6 -14
  2. data/HISTORY +33 -11
  3. data/README.rdoc +7 -7
  4. data/Rakefile +80 -77
  5. data/ext/libxml/extconf.h +4 -5
  6. data/ext/libxml/extconf.rb +57 -118
  7. data/ext/libxml/libxml.c +4 -0
  8. data/ext/libxml/ruby_xml.c +977 -893
  9. data/ext/libxml/ruby_xml.h +20 -10
  10. data/ext/libxml/ruby_xml_attr.c +333 -333
  11. data/ext/libxml/ruby_xml_attr_decl.c +2 -2
  12. data/ext/libxml/ruby_xml_cbg.c +85 -85
  13. data/ext/libxml/ruby_xml_document.c +1133 -1147
  14. data/ext/libxml/ruby_xml_dtd.c +261 -268
  15. data/ext/libxml/ruby_xml_encoding.c +262 -260
  16. data/ext/libxml/ruby_xml_encoding.h +19 -19
  17. data/ext/libxml/ruby_xml_html_parser_context.c +337 -338
  18. data/ext/libxml/ruby_xml_input_cbg.c +191 -191
  19. data/ext/libxml/ruby_xml_io.c +52 -50
  20. data/ext/libxml/ruby_xml_namespace.c +2 -2
  21. data/ext/libxml/ruby_xml_node.c +1446 -1452
  22. data/ext/libxml/ruby_xml_parser_context.c +999 -1001
  23. data/ext/libxml/ruby_xml_reader.c +1226 -1228
  24. data/ext/libxml/ruby_xml_relaxng.c +110 -111
  25. data/ext/libxml/ruby_xml_sax2_handler.c +326 -328
  26. data/ext/libxml/ruby_xml_schema.c +300 -301
  27. data/ext/libxml/ruby_xml_version.h +3 -3
  28. data/ext/libxml/ruby_xml_writer.c +34 -16
  29. data/ext/libxml/ruby_xml_xpath.c +188 -187
  30. data/ext/libxml/ruby_xml_xpath_context.c +360 -361
  31. data/ext/libxml/ruby_xml_xpath_object.c +335 -335
  32. data/libxml-ruby.gemspec +47 -44
  33. data/test/tc_attr.rb +5 -7
  34. data/test/tc_attr_decl.rb +5 -6
  35. data/test/tc_attributes.rb +1 -2
  36. data/test/tc_canonicalize.rb +1 -2
  37. data/test/tc_deprecated_require.rb +1 -2
  38. data/test/tc_document.rb +4 -5
  39. data/test/tc_document_write.rb +2 -3
  40. data/test/tc_dtd.rb +4 -5
  41. data/test/tc_encoding.rb +126 -126
  42. data/test/tc_encoding_sax.rb +4 -3
  43. data/test/tc_error.rb +14 -15
  44. data/test/tc_html_parser.rb +15 -7
  45. data/test/tc_html_parser_context.rb +1 -2
  46. data/test/tc_namespace.rb +2 -3
  47. data/test/tc_namespaces.rb +5 -6
  48. data/test/tc_node.rb +2 -3
  49. data/test/tc_node_cdata.rb +2 -3
  50. data/test/tc_node_comment.rb +1 -2
  51. data/test/tc_node_copy.rb +1 -2
  52. data/test/tc_node_edit.rb +5 -7
  53. data/test/tc_node_pi.rb +1 -2
  54. data/test/tc_node_text.rb +2 -3
  55. data/test/tc_node_write.rb +2 -3
  56. data/test/tc_node_xlink.rb +1 -2
  57. data/test/tc_parser.rb +18 -24
  58. data/test/tc_parser_context.rb +6 -7
  59. data/test/tc_properties.rb +1 -2
  60. data/test/tc_reader.rb +9 -10
  61. data/test/tc_relaxng.rb +4 -5
  62. data/test/tc_sax_parser.rb +9 -10
  63. data/test/tc_schema.rb +4 -5
  64. data/test/tc_traversal.rb +1 -2
  65. data/test/tc_writer.rb +1 -2
  66. data/test/tc_xinclude.rb +1 -2
  67. data/test/tc_xml.rb +1 -2
  68. data/test/tc_xpath.rb +8 -9
  69. data/test/tc_xpath_context.rb +3 -4
  70. data/test/tc_xpath_expression.rb +3 -4
  71. data/test/tc_xpointer.rb +1 -3
  72. data/test/test_helper.rb +3 -1
  73. data/test/test_suite.rb +0 -1
  74. metadata +90 -72
  75. data/test/etc_doc_to_s.rb +0 -21
  76. data/test/ets_doc_file.rb +0 -17
  77. data/test/ets_doc_to_s.rb +0 -23
  78. data/test/ets_gpx.rb +0 -28
  79. data/test/ets_node_gc.rb +0 -23
  80. data/test/ets_test.xml +0 -2
  81. data/test/ets_tsr.rb +0 -11
  82. data/test/model/kml_sample.xml +0 -915
  83. data/test/remove_test.rb +0 -9
  84. data/test/tc_gc.rb +0 -86
  85. data/test/tc_parser.rb.orig +0 -384
@@ -1,1001 +1,999 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- #include "ruby_libxml.h"
4
- #include "ruby_xml_parser_context.h"
5
-
6
- VALUE cXMLParserContext;
7
- static ID IO_ATTR;
8
-
9
- /*
10
- * Document-class: LibXML::XML::Parser::Context
11
- *
12
- * The XML::Parser::Context class provides in-depth control over how
13
- * a document is parsed.
14
- */
15
-
16
- static void rxml_parser_context_free(xmlParserCtxtPtr ctxt)
17
- {
18
- xmlFreeParserCtxt(ctxt);
19
- }
20
-
21
- static VALUE rxml_parser_context_wrap(xmlParserCtxtPtr ctxt)
22
- {
23
- return Data_Wrap_Struct(cXMLParserContext, NULL, rxml_parser_context_free, ctxt);
24
- }
25
-
26
-
27
- static VALUE rxml_parser_context_alloc(VALUE klass)
28
- {
29
- xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
30
- return Data_Wrap_Struct(klass, NULL, rxml_parser_context_free, ctxt);
31
- }
32
-
33
- /* call-seq:
34
- * XML::Parser::Context.document(document) -> XML::Parser::Context
35
- *
36
- * Creates a new parser context based on the specified document.
37
- *
38
- * Parameters:
39
- *
40
- * document - An XML::Document instance.
41
- */
42
- static VALUE rxml_parser_context_document(VALUE klass, VALUE document)
43
- {
44
- xmlParserCtxtPtr ctxt;
45
- xmlDocPtr xdoc;
46
- xmlChar *buffer;
47
- int length;
48
-
49
- if (rb_obj_is_kind_of(document, cXMLDocument) == Qfalse)
50
- rb_raise(rb_eTypeError, "Must pass an XML::Document object");
51
-
52
- Data_Get_Struct(document, xmlDoc, xdoc);
53
- xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, xdoc->encoding, 0);
54
-
55
- ctxt = xmlCreateDocParserCtxt(buffer);
56
-
57
- if (!ctxt)
58
- rxml_raise(&xmlLastError);
59
-
60
- /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
61
- xmlCtxtUseOptionsInternal (called below) initialize slightly different
62
- context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
63
- sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
64
- xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
65
-
66
- return rxml_parser_context_wrap(ctxt);
67
- }
68
-
69
- /* call-seq:
70
- * XML::Parser::Context.file(file) -> XML::Parser::Context
71
- *
72
- * Creates a new parser context based on the specified file or uri.
73
- *
74
- * Parameters:
75
- *
76
- * file - A filename or uri.
77
- */
78
- static VALUE rxml_parser_context_file(VALUE klass, VALUE file)
79
- {
80
- xmlParserCtxtPtr ctxt = xmlCreateURLParserCtxt(StringValuePtr(file), 0);
81
-
82
- if (!ctxt)
83
- rxml_raise(&xmlLastError);
84
-
85
- /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
86
- xmlCtxtUseOptionsInternal (called below) initialize slightly different
87
- context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
88
- sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
89
- xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
90
-
91
- return rxml_parser_context_wrap(ctxt);
92
- }
93
-
94
- /* call-seq:
95
- * XML::Parser::Context.string(string) -> XML::Parser::Context
96
- *
97
- * Creates a new parser context based on the specified string.
98
- *
99
- * Parameters:
100
- *
101
- * string - A string that contains the data to parse.
102
- */
103
- static VALUE rxml_parser_context_string(VALUE klass, VALUE string)
104
- {
105
- xmlParserCtxtPtr ctxt;
106
- Check_Type(string, T_STRING);
107
-
108
- if (RSTRING_LEN(string) == 0)
109
- rb_raise(rb_eArgError, "Must specify a string with one or more characters");
110
-
111
- ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(string),
112
- RSTRING_LEN(string));
113
-
114
- if (!ctxt)
115
- rxml_raise(&xmlLastError);
116
-
117
- /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
118
- xmlCtxtUseOptionsInternal (called below) initialize slightly different
119
- context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
120
- sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
121
- xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
122
-
123
- return rxml_parser_context_wrap(ctxt);
124
- }
125
-
126
- /* call-seq:
127
- * XML::Parser::Context.io(io) -> XML::Parser::Context
128
- *
129
- * Creates a new parser context based on the specified io object.
130
- *
131
- * Parameters:
132
- *
133
- * io - A ruby IO object.
134
- */
135
- static VALUE rxml_parser_context_io(VALUE klass, VALUE io)
136
- {
137
- VALUE result;
138
- xmlParserCtxtPtr ctxt;
139
- xmlParserInputBufferPtr input;
140
- xmlParserInputPtr stream;
141
-
142
- if (NIL_P(io))
143
- rb_raise(rb_eTypeError, "Must pass in an IO object");
144
-
145
- input = xmlParserInputBufferCreateIO((xmlInputReadCallback) rxml_read_callback, NULL,
146
- (void*)io, XML_CHAR_ENCODING_NONE);
147
-
148
- ctxt = xmlNewParserCtxt();
149
-
150
- if (!ctxt)
151
- {
152
- xmlFreeParserInputBuffer(input);
153
- rxml_raise(&xmlLastError);
154
- }
155
-
156
- /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
157
- xmlCtxtUseOptionsInternal (called below) initialize slightly different
158
- context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
159
- sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
160
- xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
161
-
162
- stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
163
-
164
- if (!stream)
165
- {
166
- xmlFreeParserInputBuffer(input);
167
- xmlFreeParserCtxt(ctxt);
168
- rxml_raise(&xmlLastError);
169
- }
170
- inputPush(ctxt, stream);
171
- result = rxml_parser_context_wrap(ctxt);
172
-
173
- /* Attach io object to parser so it won't get freed.*/
174
- rb_ivar_set(result, IO_ATTR, io);
175
-
176
- return result;
177
- }
178
-
179
- /*
180
- * call-seq:
181
- * context.base_uri -> "http:://libxml.org"
182
- *
183
- * Obtain the base url for this parser context.
184
- */
185
- static VALUE rxml_parser_context_base_uri_get(VALUE self)
186
- {
187
- xmlParserCtxtPtr ctxt;
188
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
189
-
190
- if (ctxt->input && ctxt->input->filename)
191
- return rxml_new_cstr(ctxt->input->filename, ctxt->encoding);
192
- else
193
- return Qnil;
194
- }
195
-
196
- /*
197
- * call-seq:
198
- * context.base_uri = "http:://libxml.org"
199
- *
200
- * Sets the base url for this parser context.
201
- */
202
- static VALUE rxml_parser_context_base_uri_set(VALUE self, VALUE url)
203
- {
204
- xmlParserCtxtPtr ctxt;
205
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
206
-
207
- Check_Type(url, T_STRING);
208
-
209
- if (ctxt->input && !ctxt->input->filename)
210
- {
211
- const xmlChar * xurl = StringValuePtr(url);
212
- ctxt->input->filename = (char *) xmlStrdup(xurl);
213
- }
214
- return self;
215
- }
216
-
217
- /*
218
- * call-seq:
219
- * context.close -> nil
220
- *
221
- * Closes the underlying input streams. This is useful when parsing a large amount of
222
- * files and you want to close the files without relying on Ruby's garbage collector
223
- * to run.
224
- */
225
- static VALUE rxml_parser_context_close(VALUE self)
226
- {
227
- xmlParserCtxtPtr ctxt;
228
- xmlParserInputPtr xinput;
229
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
230
-
231
- while ((xinput = inputPop(ctxt)) != NULL)
232
- {
233
- xmlFreeInputStream(xinput);
234
- }
235
- return Qnil;
236
- }
237
-
238
- /*
239
- * call-seq:
240
- * context.data_directory -> "dir"
241
- *
242
- * Obtain the data directory associated with this context.
243
- */
244
- static VALUE rxml_parser_context_data_directory_get(VALUE self)
245
- {
246
- xmlParserCtxtPtr ctxt;
247
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
248
-
249
- if (ctxt->directory == NULL)
250
- return (Qnil);
251
- else
252
- return (rxml_new_cstr(ctxt->directory, ctxt->encoding));
253
- }
254
-
255
- /*
256
- * call-seq:
257
- * context.depth -> num
258
- *
259
- * Obtain the depth of this context.
260
- */
261
- static VALUE rxml_parser_context_depth_get(VALUE self)
262
- {
263
- xmlParserCtxtPtr ctxt;
264
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
265
-
266
- return (INT2NUM(ctxt->depth));
267
- }
268
-
269
- /*
270
- * call-seq:
271
- * context.disable_cdata? -> (true|false)
272
- *
273
- * Determine whether CDATA nodes will be created in this context.
274
- */
275
- static VALUE rxml_parser_context_disable_cdata_q(VALUE self)
276
- {
277
- xmlParserCtxtPtr ctxt;
278
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
279
-
280
- /* LibXML controls this internally with the default SAX handler. */
281
- if (ctxt->sax && ctxt->sax->cdataBlock)
282
- return (Qfalse);
283
- else
284
- return (Qtrue);
285
- }
286
-
287
- /*
288
- * call-seq:
289
- * context.disable_cdata = (true|false)
290
- *
291
- * Control whether CDATA nodes will be created in this context.
292
- */
293
- static VALUE rxml_parser_context_disable_cdata_set(VALUE self, VALUE bool)
294
- {
295
- xmlParserCtxtPtr ctxt;
296
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
297
-
298
- if (ctxt->sax == NULL)
299
- rb_raise(rb_eRuntimeError, "Sax handler is not yet set");
300
-
301
- /* LibXML controls this internally with the default SAX handler. */
302
- if (bool)
303
- ctxt->sax->cdataBlock = NULL;
304
- else
305
- ctxt->sax->cdataBlock = xmlDefaultSAXHandler.cdataBlock;
306
-
307
- return bool;
308
- }
309
-
310
- /*
311
- * call-seq:
312
- * context.disable_sax? -> (true|false)
313
- *
314
- * Determine whether SAX-based processing is disabled
315
- * in this context.
316
- */
317
- static VALUE rxml_parser_context_disable_sax_q(VALUE self)
318
- {
319
- xmlParserCtxtPtr ctxt;
320
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
321
-
322
- if (ctxt->disableSAX)
323
- return (Qtrue);
324
- else
325
- return (Qfalse);
326
- }
327
-
328
- /*
329
- * call-seq:
330
- * context.docbook? -> (true|false)
331
- *
332
- * Determine whether this is a docbook context.
333
- */
334
- static VALUE rxml_parser_context_docbook_q(VALUE self)
335
- {
336
- xmlParserCtxtPtr ctxt;
337
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
338
-
339
- if (ctxt->html == 2) // TODO check this
340
- return (Qtrue);
341
- else
342
- return (Qfalse);
343
- }
344
-
345
- /*
346
- * call-seq:
347
- * context.encoding -> XML::Encoding::UTF_8
348
- *
349
- * Obtain the character encoding identifier used in
350
- * this context.
351
- */
352
- static VALUE rxml_parser_context_encoding_get(VALUE self)
353
- {
354
- xmlParserCtxtPtr ctxt;
355
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
356
- return INT2NUM(xmlParseCharEncoding(ctxt->encoding));
357
- }
358
-
359
- /*
360
- * call-seq:
361
- * context.encoding = XML::Encoding::UTF_8
362
- *
363
- * Sets the character encoding for this context.
364
- */
365
- static VALUE rxml_parser_context_encoding_set(VALUE self, VALUE encoding)
366
- {
367
- xmlParserCtxtPtr ctxt;
368
- int result;
369
- const char* xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(encoding));
370
- xmlCharEncodingHandlerPtr hdlr = xmlFindCharEncodingHandler(xencoding);
371
-
372
- if (!hdlr)
373
- rb_raise(rb_eArgError, "Unknown encoding: %i", NUM2INT(encoding));
374
-
375
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
376
- result = xmlSwitchToEncoding(ctxt, hdlr);
377
-
378
- if (result != 0)
379
- rxml_raise(&xmlLastError);
380
-
381
- if (ctxt->encoding != NULL)
382
- xmlFree((xmlChar *) ctxt->encoding);
383
-
384
- ctxt->encoding = xmlStrdup((const xmlChar *) xencoding);
385
- return self;
386
- }
387
-
388
- /*
389
- * call-seq:
390
- * context.errno -> num
391
- *
392
- * Obtain the last-error number in this context.
393
- */
394
- static VALUE rxml_parser_context_errno_get(VALUE self)
395
- {
396
- xmlParserCtxtPtr ctxt;
397
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
398
-
399
- return (INT2NUM(ctxt->errNo));
400
- }
401
-
402
- /*
403
- * call-seq:
404
- * context.html? -> (true|false)
405
- *
406
- * Determine whether this is an html context.
407
- */
408
- static VALUE rxml_parser_context_html_q(VALUE self)
409
- {
410
- xmlParserCtxtPtr ctxt;
411
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
412
-
413
- if (ctxt->html == 1)
414
- return (Qtrue);
415
- else
416
- return (Qfalse);
417
- }
418
-
419
- /*
420
- * call-seq:
421
- * context.max_num_streams -> num
422
- *
423
- * Obtain the limit on the number of IO streams opened in
424
- * this context.
425
- */
426
- static VALUE rxml_parser_context_io_max_num_streams_get(VALUE self)
427
- {
428
- // TODO alias to max_streams and dep this?
429
- xmlParserCtxtPtr ctxt;
430
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
431
-
432
- return (INT2NUM(ctxt->inputMax));
433
- }
434
-
435
- /*
436
- * call-seq:
437
- * context.num_streams -> "dir"
438
- *
439
- * Obtain the actual number of IO streams in this
440
- * context.
441
- */
442
- static VALUE rxml_parser_context_io_num_streams_get(VALUE self)
443
- {
444
- xmlParserCtxtPtr ctxt;
445
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
446
-
447
- return (INT2NUM(ctxt->inputNr));
448
- }
449
-
450
- /*
451
- * call-seq:
452
- * context.keep_blanks? -> (true|false)
453
- *
454
- * Determine whether parsers in this context retain
455
- * whitespace.
456
- */
457
- static VALUE rxml_parser_context_keep_blanks_q(VALUE self)
458
- {
459
- xmlParserCtxtPtr ctxt;
460
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
461
-
462
- if (ctxt->keepBlanks)
463
- return (Qtrue);
464
- else
465
- return (Qfalse);
466
- }
467
-
468
- /*
469
- * call-seq:
470
- * context.name_depth -> num
471
- *
472
- * Obtain the name depth for this context.
473
- */
474
- static VALUE rxml_parser_context_name_depth_get(VALUE self)
475
- {
476
- xmlParserCtxtPtr ctxt;
477
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
478
-
479
- return (INT2NUM(ctxt->nameNr));
480
- }
481
-
482
- /*
483
- * call-seq:
484
- * context.name_depth_max -> num
485
- *
486
- * Obtain the maximum name depth for this context.
487
- */
488
- static VALUE rxml_parser_context_name_depth_max_get(VALUE self)
489
- {
490
- xmlParserCtxtPtr ctxt;
491
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
492
-
493
- return (INT2NUM(ctxt->nameMax));
494
- }
495
-
496
- /*
497
- * call-seq:
498
- * context.name_node -> "name"
499
- *
500
- * Obtain the name node for this context.
501
- */
502
- static VALUE rxml_parser_context_name_node_get(VALUE self)
503
- {
504
- xmlParserCtxtPtr ctxt;
505
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
506
-
507
- if (ctxt->name == NULL)
508
- return (Qnil);
509
- else
510
- return (rxml_new_cstr((const char*) ctxt->name, ctxt->encoding));
511
- }
512
-
513
- /*
514
- * call-seq:
515
- * context.name_tab -> ["name", ..., "name"]
516
- *
517
- * Obtain the name table for this context.
518
- */
519
- static VALUE rxml_parser_context_name_tab_get(VALUE self)
520
- {
521
- int i;
522
- xmlParserCtxtPtr ctxt;
523
- VALUE tab_ary;
524
-
525
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
526
-
527
- if (ctxt->nameTab == NULL)
528
- return (Qnil);
529
-
530
- tab_ary = rb_ary_new();
531
-
532
- for (i = (ctxt->nameNr - 1); i >= 0; i--)
533
- {
534
- if (ctxt->nameTab[i] == NULL)
535
- continue;
536
- else
537
- rb_ary_push(tab_ary, rxml_new_cstr((const char*) ctxt->nameTab[i], ctxt->encoding));
538
- }
539
-
540
- return (tab_ary);
541
- }
542
-
543
- /*
544
- * call-seq:
545
- * context.node_depth -> num
546
- *
547
- * Obtain the node depth for this context.
548
- */
549
- static VALUE rxml_parser_context_node_depth_get(VALUE self)
550
- {
551
- xmlParserCtxtPtr ctxt;
552
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
553
-
554
- return (INT2NUM(ctxt->nodeNr));
555
- }
556
-
557
- /*
558
- * call-seq:
559
- * context.node -> node
560
- *
561
- * Obtain the root node of this context.
562
- */
563
- static VALUE rxml_parser_context_node_get(VALUE self)
564
- {
565
- xmlParserCtxtPtr ctxt;
566
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
567
-
568
- if (ctxt->node == NULL)
569
- return (Qnil);
570
- else
571
- return (rxml_node_wrap(ctxt->node));
572
- }
573
-
574
- /*
575
- * call-seq:
576
- * context.node_depth_max -> num
577
- *
578
- * Obtain the maximum node depth for this context.
579
- */
580
- static VALUE rxml_parser_context_node_depth_max_get(VALUE self)
581
- {
582
- xmlParserCtxtPtr ctxt;
583
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
584
-
585
- return (INT2NUM(ctxt->nodeMax));
586
- }
587
-
588
- /*
589
- * call-seq:
590
- * context.num_chars -> num
591
- *
592
- * Obtain the number of characters in this context.
593
- */
594
- static VALUE rxml_parser_context_num_chars_get(VALUE self)
595
- {
596
- xmlParserCtxtPtr ctxt;
597
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
598
-
599
- return (LONG2NUM(ctxt->nbChars));
600
- }
601
-
602
-
603
- /*
604
- * call-seq:
605
- * context.options > XML::Parser::Options::NOENT
606
- *
607
- * Returns the parser options for this context. Multiple
608
- * options can be combined by using Bitwise OR (|).
609
- */
610
- static VALUE rxml_parser_context_options_get(VALUE self)
611
- {
612
- xmlParserCtxtPtr ctxt;
613
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
614
-
615
- return INT2NUM(ctxt->options);
616
- }
617
-
618
- /*
619
- * call-seq:
620
- * context.options = XML::Parser::Options::NOENT |
621
- XML::Parser::Options::NOCDATA
622
- *
623
- * Provides control over the execution of a parser. Valid values
624
- * are the constants defined on XML::Parser::Options. Multiple
625
- * options can be combined by using Bitwise OR (|).
626
- */
627
- static VALUE rxml_parser_context_options_set(VALUE self, VALUE options)
628
- {
629
- int result;
630
- xmlParserCtxtPtr ctxt;
631
- Check_Type(options, T_FIXNUM);
632
-
633
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
634
- result = xmlCtxtUseOptions(ctxt, NUM2INT(options));
635
-
636
- return self;
637
- }
638
-
639
- /*
640
- * call-seq:
641
- * context.recovery? -> (true|false)
642
- *
643
- * Determine whether recovery mode is enabled in this
644
- * context.
645
- */
646
- static VALUE rxml_parser_context_recovery_q(VALUE self)
647
- {
648
- xmlParserCtxtPtr ctxt;
649
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
650
-
651
- if (ctxt->recovery)
652
- return (Qtrue);
653
- else
654
- return (Qfalse);
655
- }
656
-
657
- /*
658
- * call-seq:
659
- * context.recovery = true|false
660
- *
661
- * Control whether recovery mode is enabled in this
662
- * context.
663
- */
664
- static VALUE rxml_parser_context_recovery_set(VALUE self, VALUE bool)
665
- {
666
- xmlParserCtxtPtr ctxt;
667
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
668
-
669
- if (TYPE(bool) == T_FALSE)
670
- {
671
- ctxt->recovery = 0;
672
- return (Qfalse);
673
- }
674
- else
675
- {
676
- ctxt->recovery = 1;
677
- return (Qtrue);
678
- }
679
- }
680
-
681
- /*
682
- * call-seq:
683
- * context.replace_entities? -> (true|false)
684
- *
685
- * Determine whether external entity replacement is enabled in this
686
- * context.
687
- */
688
- static VALUE rxml_parser_context_replace_entities_q(VALUE self)
689
- {
690
- xmlParserCtxtPtr ctxt;
691
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
692
-
693
- if (ctxt->replaceEntities)
694
- return (Qtrue);
695
- else
696
- return (Qfalse);
697
- }
698
-
699
- /*
700
- * call-seq:
701
- * context.replace_entities = true|false
702
- *
703
- * Control whether external entity replacement is enabled in this
704
- * context.
705
- */
706
- static VALUE rxml_parser_context_replace_entities_set(VALUE self, VALUE bool)
707
- {
708
- xmlParserCtxtPtr ctxt;
709
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
710
-
711
- if (TYPE(bool) == T_FALSE)
712
- {
713
- ctxt->replaceEntities = 0;
714
- return (Qfalse);
715
- }
716
- else
717
- {
718
- ctxt->replaceEntities = 1;
719
- return (Qtrue);
720
- }
721
- }
722
-
723
- /*
724
- * call-seq:
725
- * context.space_depth -> num
726
- *
727
- * Obtain the space depth for this context.
728
- */
729
- static VALUE rxml_parser_context_space_depth_get(VALUE self)
730
- {
731
- xmlParserCtxtPtr ctxt;
732
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
733
-
734
- return (INT2NUM(ctxt->spaceNr));
735
- }
736
-
737
- /*
738
- * call-seq:
739
- * context.space_depth -> num
740
- *
741
- * Obtain the maximum space depth for this context.
742
- */
743
- static VALUE rxml_parser_context_space_depth_max_get(VALUE self)
744
- {
745
- xmlParserCtxtPtr ctxt;
746
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
747
-
748
- return (INT2NUM(ctxt->spaceMax));
749
- }
750
-
751
- /*
752
- * call-seq:
753
- * context.subset_external? -> (true|false)
754
- *
755
- * Determine whether this context is a subset of an
756
- * external context.
757
- */
758
- static VALUE rxml_parser_context_subset_external_q(VALUE self)
759
- {
760
- xmlParserCtxtPtr ctxt;
761
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
762
-
763
- if (ctxt->inSubset == 2)
764
- return (Qtrue);
765
- else
766
- return (Qfalse);
767
- }
768
-
769
- /*
770
- * call-seq:
771
- * context.subset_internal? -> (true|false)
772
- *
773
- * Determine whether this context is a subset of an
774
- * internal context.
775
- */
776
- static VALUE rxml_parser_context_subset_internal_q(VALUE self)
777
- {
778
- xmlParserCtxtPtr ctxt;
779
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
780
-
781
- if (ctxt->inSubset == 1)
782
- return (Qtrue);
783
- else
784
- return (Qfalse);
785
- }
786
-
787
- /*
788
- * call-seq:
789
- * context.subset_internal_name -> "name"
790
- *
791
- * Obtain this context's subset name (valid only if
792
- * either of subset_external? or subset_internal?
793
- * is true).
794
- */
795
- static VALUE rxml_parser_context_subset_name_get(VALUE self)
796
- {
797
- xmlParserCtxtPtr ctxt;
798
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
799
-
800
- if (ctxt->intSubName == NULL)
801
- return (Qnil);
802
- else
803
- return (rxml_new_cstr((const char*) ctxt->intSubName, ctxt->encoding));
804
- }
805
-
806
- /*
807
- * call-seq:
808
- * context.subset_external_uri -> "uri"
809
- *
810
- * Obtain this context's external subset URI. (valid only if
811
- * either of subset_external? or subset_internal?
812
- * is true).
813
- */
814
- static VALUE rxml_parser_context_subset_external_uri_get(VALUE self)
815
- {
816
- xmlParserCtxtPtr ctxt;
817
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
818
-
819
- if (ctxt->extSubURI == NULL)
820
- return (Qnil);
821
- else
822
- return (rxml_new_cstr((const char*) ctxt->extSubURI, ctxt->encoding));
823
- }
824
-
825
- /*
826
- * call-seq:
827
- * context.subset_external_system_id -> "system_id"
828
- *
829
- * Obtain this context's external subset system identifier.
830
- * (valid only if either of subset_external? or subset_internal?
831
- * is true).
832
- */
833
- static VALUE rxml_parser_context_subset_external_system_id_get(VALUE self)
834
- {
835
- xmlParserCtxtPtr ctxt;
836
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
837
-
838
- if (ctxt->extSubSystem == NULL)
839
- return (Qnil);
840
- else
841
- return (rxml_new_cstr((const char*) ctxt->extSubSystem, ctxt->encoding));
842
- }
843
-
844
- /*
845
- * call-seq:
846
- * context.standalone? -> (true|false)
847
- *
848
- * Determine whether this is a standalone context.
849
- */
850
- static VALUE rxml_parser_context_standalone_q(VALUE self)
851
- {
852
- xmlParserCtxtPtr ctxt;
853
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
854
-
855
- if (ctxt->standalone)
856
- return (Qtrue);
857
- else
858
- return (Qfalse);
859
- }
860
-
861
- /*
862
- * call-seq:
863
- * context.stats? -> (true|false)
864
- *
865
- * Determine whether this context maintains statistics.
866
- */
867
- static VALUE rxml_parser_context_stats_q(VALUE self)
868
- {
869
- xmlParserCtxtPtr ctxt;
870
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
871
-
872
- if (ctxt->record_info)
873
- return (Qtrue);
874
- else
875
- return (Qfalse);
876
- }
877
-
878
- /*
879
- * call-seq:
880
- * context.valid? -> (true|false)
881
- *
882
- * Determine whether this context is valid.
883
- */
884
- static VALUE rxml_parser_context_valid_q(VALUE self)
885
- {
886
- xmlParserCtxtPtr ctxt;
887
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
888
-
889
- if (ctxt->valid)
890
- return (Qtrue);
891
- else
892
- return (Qfalse);
893
- }
894
-
895
- /*
896
- * call-seq:
897
- * context.validate? -> (true|false)
898
- *
899
- * Determine whether validation is enabled in this context.
900
- */
901
- static VALUE rxml_parser_context_validate_q(VALUE self)
902
- {
903
- xmlParserCtxtPtr ctxt;
904
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
905
-
906
- if (ctxt->validate)
907
- return (Qtrue);
908
- else
909
- return (Qfalse);
910
- }
911
-
912
- /*
913
- * call-seq:
914
- * context.version -> "version"
915
- *
916
- * Obtain this context's version identifier.
917
- */
918
- static VALUE rxml_parser_context_version_get(VALUE self)
919
- {
920
- xmlParserCtxtPtr ctxt;
921
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
922
-
923
- if (ctxt->version == NULL)
924
- return (Qnil);
925
- else
926
- return (rxml_new_cstr((const char*) ctxt->version, ctxt->encoding));
927
- }
928
-
929
- /*
930
- * call-seq:
931
- * context.well_formed? -> (true|false)
932
- *
933
- * Determine whether this context contains well-formed XML.
934
- */
935
- static VALUE rxml_parser_context_well_formed_q(VALUE self)
936
- {
937
- xmlParserCtxtPtr ctxt;
938
- Data_Get_Struct(self, xmlParserCtxt, ctxt);
939
-
940
- if (ctxt->wellFormed)
941
- return (Qtrue);
942
- else
943
- return (Qfalse);
944
- }
945
-
946
- void rxml_init_parser_context(void)
947
- {
948
- IO_ATTR = ID2SYM(rb_intern("@io"));
949
-
950
- cXMLParserContext = rb_define_class_under(cXMLParser, "Context", rb_cObject);
951
- rb_define_alloc_func(cXMLParserContext, rxml_parser_context_alloc);
952
-
953
- rb_define_singleton_method(cXMLParserContext, "document", rxml_parser_context_document, 1);
954
- rb_define_singleton_method(cXMLParserContext, "file", rxml_parser_context_file, 1);
955
- rb_define_singleton_method(cXMLParserContext, "io", rxml_parser_context_io, 1);
956
- rb_define_singleton_method(cXMLParserContext, "string", rxml_parser_context_string, 1);
957
-
958
- rb_define_method(cXMLParserContext, "base_uri", rxml_parser_context_base_uri_get, 0);
959
- rb_define_method(cXMLParserContext, "base_uri=", rxml_parser_context_base_uri_set, 1);
960
- rb_define_method(cXMLParserContext, "close", rxml_parser_context_close, 0);
961
- rb_define_method(cXMLParserContext, "data_directory", rxml_parser_context_data_directory_get, 0);
962
- rb_define_method(cXMLParserContext, "depth", rxml_parser_context_depth_get, 0);
963
- rb_define_method(cXMLParserContext, "disable_cdata?", rxml_parser_context_disable_cdata_q, 0);
964
- rb_define_method(cXMLParserContext, "disable_cdata=", rxml_parser_context_disable_cdata_set, 1);
965
- rb_define_method(cXMLParserContext, "disable_sax?", rxml_parser_context_disable_sax_q, 0);
966
- rb_define_method(cXMLParserContext, "docbook?", rxml_parser_context_docbook_q, 0);
967
- rb_define_method(cXMLParserContext, "encoding", rxml_parser_context_encoding_get, 0);
968
- rb_define_method(cXMLParserContext, "encoding=", rxml_parser_context_encoding_set, 1);
969
- rb_define_method(cXMLParserContext, "errno", rxml_parser_context_errno_get, 0);
970
- rb_define_method(cXMLParserContext, "html?", rxml_parser_context_html_q, 0);
971
- rb_define_method(cXMLParserContext, "io_max_num_streams", rxml_parser_context_io_max_num_streams_get, 0);
972
- rb_define_method(cXMLParserContext, "io_num_streams", rxml_parser_context_io_num_streams_get, 0);
973
- rb_define_method(cXMLParserContext, "keep_blanks?", rxml_parser_context_keep_blanks_q, 0);
974
- rb_define_method(cXMLParserContext, "name_node", rxml_parser_context_name_node_get, 0);
975
- rb_define_method(cXMLParserContext, "name_depth", rxml_parser_context_name_depth_get, 0);
976
- rb_define_method(cXMLParserContext, "name_depth_max", rxml_parser_context_name_depth_max_get, 0);
977
- rb_define_method(cXMLParserContext, "name_tab", rxml_parser_context_name_tab_get, 0);
978
- rb_define_method(cXMLParserContext, "node", rxml_parser_context_node_get, 0);
979
- rb_define_method(cXMLParserContext, "node_depth", rxml_parser_context_node_depth_get, 0);
980
- rb_define_method(cXMLParserContext, "node_depth_max", rxml_parser_context_node_depth_max_get, 0);
981
- rb_define_method(cXMLParserContext, "num_chars", rxml_parser_context_num_chars_get, 0);
982
- rb_define_method(cXMLParserContext, "options", rxml_parser_context_options_get, 0);
983
- rb_define_method(cXMLParserContext, "options=", rxml_parser_context_options_set, 1);
984
- rb_define_method(cXMLParserContext, "recovery?", rxml_parser_context_recovery_q, 0);
985
- rb_define_method(cXMLParserContext, "recovery=", rxml_parser_context_recovery_set, 1);
986
- rb_define_method(cXMLParserContext, "replace_entities?", rxml_parser_context_replace_entities_q, 0);
987
- rb_define_method(cXMLParserContext, "replace_entities=", rxml_parser_context_replace_entities_set, 1);
988
- rb_define_method(cXMLParserContext, "space_depth", rxml_parser_context_space_depth_get, 0);
989
- rb_define_method(cXMLParserContext, "space_depth_max", rxml_parser_context_space_depth_max_get, 0);
990
- rb_define_method(cXMLParserContext, "subset_external?", rxml_parser_context_subset_external_q, 0);
991
- rb_define_method(cXMLParserContext, "subset_external_system_id", rxml_parser_context_subset_external_system_id_get, 0);
992
- rb_define_method(cXMLParserContext, "subset_external_uri", rxml_parser_context_subset_external_uri_get, 0);
993
- rb_define_method(cXMLParserContext, "subset_internal?", rxml_parser_context_subset_internal_q, 0);
994
- rb_define_method(cXMLParserContext, "subset_internal_name", rxml_parser_context_subset_name_get, 0);
995
- rb_define_method(cXMLParserContext, "stats?", rxml_parser_context_stats_q, 0);
996
- rb_define_method(cXMLParserContext, "standalone?", rxml_parser_context_standalone_q, 0);
997
- rb_define_method(cXMLParserContext, "valid", rxml_parser_context_valid_q, 0);
998
- rb_define_method(cXMLParserContext, "validate?", rxml_parser_context_validate_q, 0);
999
- rb_define_method(cXMLParserContext, "version", rxml_parser_context_version_get, 0);
1000
- rb_define_method(cXMLParserContext, "well_formed?", rxml_parser_context_well_formed_q, 0);
1001
- }
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #include "ruby_libxml.h"
4
+ #include "ruby_xml_parser_context.h"
5
+
6
+ VALUE cXMLParserContext;
7
+ static ID IO_ATTR;
8
+
9
+ /*
10
+ * Document-class: LibXML::XML::Parser::Context
11
+ *
12
+ * The XML::Parser::Context class provides in-depth control over how
13
+ * a document is parsed.
14
+ */
15
+
16
+ static void rxml_parser_context_free(xmlParserCtxtPtr ctxt)
17
+ {
18
+ xmlFreeParserCtxt(ctxt);
19
+ }
20
+
21
+ static VALUE rxml_parser_context_wrap(xmlParserCtxtPtr ctxt)
22
+ {
23
+ return Data_Wrap_Struct(cXMLParserContext, NULL, rxml_parser_context_free, ctxt);
24
+ }
25
+
26
+
27
+ static VALUE rxml_parser_context_alloc(VALUE klass)
28
+ {
29
+ xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
30
+ return Data_Wrap_Struct(klass, NULL, rxml_parser_context_free, ctxt);
31
+ }
32
+
33
+ /* call-seq:
34
+ * XML::Parser::Context.document(document) -> XML::Parser::Context
35
+ *
36
+ * Creates a new parser context based on the specified document.
37
+ *
38
+ * Parameters:
39
+ *
40
+ * document - An XML::Document instance.
41
+ */
42
+ static VALUE rxml_parser_context_document(VALUE klass, VALUE document)
43
+ {
44
+ xmlParserCtxtPtr ctxt;
45
+ xmlDocPtr xdoc;
46
+ xmlChar *buffer;
47
+ int length;
48
+
49
+ if (rb_obj_is_kind_of(document, cXMLDocument) == Qfalse)
50
+ rb_raise(rb_eTypeError, "Must pass an XML::Document object");
51
+
52
+ Data_Get_Struct(document, xmlDoc, xdoc);
53
+ xmlDocDumpFormatMemoryEnc(xdoc, &buffer, &length, (const char*)xdoc->encoding, 0);
54
+
55
+ ctxt = xmlCreateDocParserCtxt(buffer);
56
+
57
+ if (!ctxt)
58
+ rxml_raise(&xmlLastError);
59
+
60
+ /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
61
+ xmlCtxtUseOptionsInternal (called below) initialize slightly different
62
+ context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
63
+ sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
64
+ xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
65
+
66
+ return rxml_parser_context_wrap(ctxt);
67
+ }
68
+
69
+ /* call-seq:
70
+ * XML::Parser::Context.file(file) -> XML::Parser::Context
71
+ *
72
+ * Creates a new parser context based on the specified file or uri.
73
+ *
74
+ * Parameters:
75
+ *
76
+ * file - A filename or uri.
77
+ */
78
+ static VALUE rxml_parser_context_file(VALUE klass, VALUE file)
79
+ {
80
+ xmlParserCtxtPtr ctxt = xmlCreateURLParserCtxt(StringValuePtr(file), 0);
81
+
82
+ if (!ctxt)
83
+ rxml_raise(&xmlLastError);
84
+
85
+ /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
86
+ xmlCtxtUseOptionsInternal (called below) initialize slightly different
87
+ context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
88
+ sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
89
+ xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
90
+
91
+ return rxml_parser_context_wrap(ctxt);
92
+ }
93
+
94
+ /* call-seq:
95
+ * XML::Parser::Context.string(string) -> XML::Parser::Context
96
+ *
97
+ * Creates a new parser context based on the specified string.
98
+ *
99
+ * Parameters:
100
+ *
101
+ * string - A string that contains the data to parse.
102
+ */
103
+ static VALUE rxml_parser_context_string(VALUE klass, VALUE string)
104
+ {
105
+ xmlParserCtxtPtr ctxt;
106
+ Check_Type(string, T_STRING);
107
+
108
+ if (RSTRING_LEN(string) == 0)
109
+ rb_raise(rb_eArgError, "Must specify a string with one or more characters");
110
+
111
+ ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(string), (int)RSTRING_LEN(string));
112
+
113
+ if (!ctxt)
114
+ rxml_raise(&xmlLastError);
115
+
116
+ /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
117
+ xmlCtxtUseOptionsInternal (called below) initialize slightly different
118
+ context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
119
+ sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
120
+ xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
121
+
122
+ return rxml_parser_context_wrap(ctxt);
123
+ }
124
+
125
+ /* call-seq:
126
+ * XML::Parser::Context.io(io) -> XML::Parser::Context
127
+ *
128
+ * Creates a new parser context based on the specified io object.
129
+ *
130
+ * Parameters:
131
+ *
132
+ * io - A ruby IO object.
133
+ */
134
+ static VALUE rxml_parser_context_io(VALUE klass, VALUE io)
135
+ {
136
+ VALUE result;
137
+ xmlParserCtxtPtr ctxt;
138
+ xmlParserInputBufferPtr input;
139
+ xmlParserInputPtr stream;
140
+
141
+ if (NIL_P(io))
142
+ rb_raise(rb_eTypeError, "Must pass in an IO object");
143
+
144
+ input = xmlParserInputBufferCreateIO((xmlInputReadCallback) rxml_read_callback, NULL,
145
+ (void*)io, XML_CHAR_ENCODING_NONE);
146
+
147
+ ctxt = xmlNewParserCtxt();
148
+
149
+ if (!ctxt)
150
+ {
151
+ xmlFreeParserInputBuffer(input);
152
+ rxml_raise(&xmlLastError);
153
+ }
154
+
155
+ /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
156
+ xmlCtxtUseOptionsInternal (called below) initialize slightly different
157
+ context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
158
+ sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
159
+ xmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
160
+
161
+ stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
162
+
163
+ if (!stream)
164
+ {
165
+ xmlFreeParserInputBuffer(input);
166
+ xmlFreeParserCtxt(ctxt);
167
+ rxml_raise(&xmlLastError);
168
+ }
169
+ inputPush(ctxt, stream);
170
+ result = rxml_parser_context_wrap(ctxt);
171
+
172
+ /* Attach io object to parser so it won't get freed.*/
173
+ rb_ivar_set(result, IO_ATTR, io);
174
+
175
+ return result;
176
+ }
177
+
178
+ /*
179
+ * call-seq:
180
+ * context.base_uri -> "http:://libxml.org"
181
+ *
182
+ * Obtain the base url for this parser context.
183
+ */
184
+ static VALUE rxml_parser_context_base_uri_get(VALUE self)
185
+ {
186
+ xmlParserCtxtPtr ctxt;
187
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
188
+
189
+ if (ctxt->input && ctxt->input->filename)
190
+ return rxml_new_cstr((const xmlChar*)ctxt->input->filename, ctxt->encoding);
191
+ else
192
+ return Qnil;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * context.base_uri = "http:://libxml.org"
198
+ *
199
+ * Sets the base url for this parser context.
200
+ */
201
+ static VALUE rxml_parser_context_base_uri_set(VALUE self, VALUE url)
202
+ {
203
+ xmlParserCtxtPtr ctxt;
204
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
205
+
206
+ Check_Type(url, T_STRING);
207
+
208
+ if (ctxt->input && !ctxt->input->filename)
209
+ {
210
+ const char* xurl = StringValuePtr(url);
211
+ ctxt->input->filename = (const char*)xmlStrdup((const xmlChar*)xurl);
212
+ }
213
+ return self;
214
+ }
215
+
216
+ /*
217
+ * call-seq:
218
+ * context.close -> nil
219
+ *
220
+ * Closes the underlying input streams. This is useful when parsing a large amount of
221
+ * files and you want to close the files without relying on Ruby's garbage collector
222
+ * to run.
223
+ */
224
+ static VALUE rxml_parser_context_close(VALUE self)
225
+ {
226
+ xmlParserCtxtPtr ctxt;
227
+ xmlParserInputPtr xinput;
228
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
229
+
230
+ while ((xinput = inputPop(ctxt)) != NULL)
231
+ {
232
+ xmlFreeInputStream(xinput);
233
+ }
234
+ return Qnil;
235
+ }
236
+
237
+ /*
238
+ * call-seq:
239
+ * context.data_directory -> "dir"
240
+ *
241
+ * Obtain the data directory associated with this context.
242
+ */
243
+ static VALUE rxml_parser_context_data_directory_get(VALUE self)
244
+ {
245
+ xmlParserCtxtPtr ctxt;
246
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
247
+
248
+ if (ctxt->directory == NULL)
249
+ return (Qnil);
250
+ else
251
+ return (rxml_new_cstr((const xmlChar*)ctxt->directory, ctxt->encoding));
252
+ }
253
+
254
+ /*
255
+ * call-seq:
256
+ * context.depth -> num
257
+ *
258
+ * Obtain the depth of this context.
259
+ */
260
+ static VALUE rxml_parser_context_depth_get(VALUE self)
261
+ {
262
+ xmlParserCtxtPtr ctxt;
263
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
264
+
265
+ return (INT2NUM(ctxt->depth));
266
+ }
267
+
268
+ /*
269
+ * call-seq:
270
+ * context.disable_cdata? -> (true|false)
271
+ *
272
+ * Determine whether CDATA nodes will be created in this context.
273
+ */
274
+ static VALUE rxml_parser_context_disable_cdata_q(VALUE self)
275
+ {
276
+ xmlParserCtxtPtr ctxt;
277
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
278
+
279
+ /* LibXML controls this internally with the default SAX handler. */
280
+ if (ctxt->sax && ctxt->sax->cdataBlock)
281
+ return (Qfalse);
282
+ else
283
+ return (Qtrue);
284
+ }
285
+
286
+ /*
287
+ * call-seq:
288
+ * context.disable_cdata = (true|false)
289
+ *
290
+ * Control whether CDATA nodes will be created in this context.
291
+ */
292
+ static VALUE rxml_parser_context_disable_cdata_set(VALUE self, VALUE value)
293
+ {
294
+ xmlParserCtxtPtr ctxt;
295
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
296
+
297
+ if (ctxt->sax == NULL)
298
+ rb_raise(rb_eRuntimeError, "Sax handler is not yet set");
299
+
300
+ /* LibXML controls this internally with the default SAX handler. */
301
+ if (value)
302
+ ctxt->sax->cdataBlock = NULL;
303
+ else
304
+ ctxt->sax->cdataBlock = xmlDefaultSAXHandler.cdataBlock;
305
+
306
+ return value;
307
+ }
308
+
309
+ /*
310
+ * call-seq:
311
+ * context.disable_sax? -> (true|false)
312
+ *
313
+ * Determine whether SAX-based processing is disabled
314
+ * in this context.
315
+ */
316
+ static VALUE rxml_parser_context_disable_sax_q(VALUE self)
317
+ {
318
+ xmlParserCtxtPtr ctxt;
319
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
320
+
321
+ if (ctxt->disableSAX)
322
+ return (Qtrue);
323
+ else
324
+ return (Qfalse);
325
+ }
326
+
327
+ /*
328
+ * call-seq:
329
+ * context.docbook? -> (true|false)
330
+ *
331
+ * Determine whether this is a docbook context.
332
+ */
333
+ static VALUE rxml_parser_context_docbook_q(VALUE self)
334
+ {
335
+ xmlParserCtxtPtr ctxt;
336
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
337
+
338
+ if (ctxt->html == 2) // TODO check this
339
+ return (Qtrue);
340
+ else
341
+ return (Qfalse);
342
+ }
343
+
344
+ /*
345
+ * call-seq:
346
+ * context.encoding -> XML::Encoding::UTF_8
347
+ *
348
+ * Obtain the character encoding identifier used in
349
+ * this context.
350
+ */
351
+ static VALUE rxml_parser_context_encoding_get(VALUE self)
352
+ {
353
+ xmlParserCtxtPtr ctxt;
354
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
355
+ return INT2NUM(xmlParseCharEncoding((const char*)ctxt->encoding));
356
+ }
357
+
358
+ /*
359
+ * call-seq:
360
+ * context.encoding = XML::Encoding::UTF_8
361
+ *
362
+ * Sets the character encoding for this context.
363
+ */
364
+ static VALUE rxml_parser_context_encoding_set(VALUE self, VALUE encoding)
365
+ {
366
+ xmlParserCtxtPtr ctxt;
367
+ int result;
368
+ const char* xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(encoding));
369
+ xmlCharEncodingHandlerPtr hdlr = xmlFindCharEncodingHandler(xencoding);
370
+
371
+ if (!hdlr)
372
+ rb_raise(rb_eArgError, "Unknown encoding: %i", NUM2INT(encoding));
373
+
374
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
375
+ result = xmlSwitchToEncoding(ctxt, hdlr);
376
+
377
+ if (result != 0)
378
+ rxml_raise(&xmlLastError);
379
+
380
+ if (ctxt->encoding != NULL)
381
+ xmlFree((xmlChar *) ctxt->encoding);
382
+
383
+ ctxt->encoding = xmlStrdup((const xmlChar *) xencoding);
384
+ return self;
385
+ }
386
+
387
+ /*
388
+ * call-seq:
389
+ * context.errno -> num
390
+ *
391
+ * Obtain the last-error number in this context.
392
+ */
393
+ static VALUE rxml_parser_context_errno_get(VALUE self)
394
+ {
395
+ xmlParserCtxtPtr ctxt;
396
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
397
+
398
+ return (INT2NUM(ctxt->errNo));
399
+ }
400
+
401
+ /*
402
+ * call-seq:
403
+ * context.html? -> (true|false)
404
+ *
405
+ * Determine whether this is an html context.
406
+ */
407
+ static VALUE rxml_parser_context_html_q(VALUE self)
408
+ {
409
+ xmlParserCtxtPtr ctxt;
410
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
411
+
412
+ if (ctxt->html == 1)
413
+ return (Qtrue);
414
+ else
415
+ return (Qfalse);
416
+ }
417
+
418
+ /*
419
+ * call-seq:
420
+ * context.max_num_streams -> num
421
+ *
422
+ * Obtain the limit on the number of IO streams opened in
423
+ * this context.
424
+ */
425
+ static VALUE rxml_parser_context_io_max_num_streams_get(VALUE self)
426
+ {
427
+ // TODO alias to max_streams and dep this?
428
+ xmlParserCtxtPtr ctxt;
429
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
430
+
431
+ return (INT2NUM(ctxt->inputMax));
432
+ }
433
+
434
+ /*
435
+ * call-seq:
436
+ * context.num_streams -> "dir"
437
+ *
438
+ * Obtain the actual number of IO streams in this
439
+ * context.
440
+ */
441
+ static VALUE rxml_parser_context_io_num_streams_get(VALUE self)
442
+ {
443
+ xmlParserCtxtPtr ctxt;
444
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
445
+
446
+ return (INT2NUM(ctxt->inputNr));
447
+ }
448
+
449
+ /*
450
+ * call-seq:
451
+ * context.keep_blanks? -> (true|false)
452
+ *
453
+ * Determine whether parsers in this context retain
454
+ * whitespace.
455
+ */
456
+ static VALUE rxml_parser_context_keep_blanks_q(VALUE self)
457
+ {
458
+ xmlParserCtxtPtr ctxt;
459
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
460
+
461
+ if (ctxt->keepBlanks)
462
+ return (Qtrue);
463
+ else
464
+ return (Qfalse);
465
+ }
466
+
467
+ /*
468
+ * call-seq:
469
+ * context.name_depth -> num
470
+ *
471
+ * Obtain the name depth for this context.
472
+ */
473
+ static VALUE rxml_parser_context_name_depth_get(VALUE self)
474
+ {
475
+ xmlParserCtxtPtr ctxt;
476
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
477
+
478
+ return (INT2NUM(ctxt->nameNr));
479
+ }
480
+
481
+ /*
482
+ * call-seq:
483
+ * context.name_depth_max -> num
484
+ *
485
+ * Obtain the maximum name depth for this context.
486
+ */
487
+ static VALUE rxml_parser_context_name_depth_max_get(VALUE self)
488
+ {
489
+ xmlParserCtxtPtr ctxt;
490
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
491
+
492
+ return (INT2NUM(ctxt->nameMax));
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * context.name_node -> "name"
498
+ *
499
+ * Obtain the name node for this context.
500
+ */
501
+ static VALUE rxml_parser_context_name_node_get(VALUE self)
502
+ {
503
+ xmlParserCtxtPtr ctxt;
504
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
505
+
506
+ if (ctxt->name == NULL)
507
+ return (Qnil);
508
+ else
509
+ return (rxml_new_cstr( ctxt->name, ctxt->encoding));
510
+ }
511
+
512
+ /*
513
+ * call-seq:
514
+ * context.name_tab -> ["name", ..., "name"]
515
+ *
516
+ * Obtain the name table for this context.
517
+ */
518
+ static VALUE rxml_parser_context_name_tab_get(VALUE self)
519
+ {
520
+ int i;
521
+ xmlParserCtxtPtr ctxt;
522
+ VALUE tab_ary;
523
+
524
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
525
+
526
+ if (ctxt->nameTab == NULL)
527
+ return (Qnil);
528
+
529
+ tab_ary = rb_ary_new();
530
+
531
+ for (i = (ctxt->nameNr - 1); i >= 0; i--)
532
+ {
533
+ if (ctxt->nameTab[i] == NULL)
534
+ continue;
535
+ else
536
+ rb_ary_push(tab_ary, rxml_new_cstr( ctxt->nameTab[i], ctxt->encoding));
537
+ }
538
+
539
+ return (tab_ary);
540
+ }
541
+
542
+ /*
543
+ * call-seq:
544
+ * context.node_depth -> num
545
+ *
546
+ * Obtain the node depth for this context.
547
+ */
548
+ static VALUE rxml_parser_context_node_depth_get(VALUE self)
549
+ {
550
+ xmlParserCtxtPtr ctxt;
551
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
552
+
553
+ return (INT2NUM(ctxt->nodeNr));
554
+ }
555
+
556
+ /*
557
+ * call-seq:
558
+ * context.node -> node
559
+ *
560
+ * Obtain the root node of this context.
561
+ */
562
+ static VALUE rxml_parser_context_node_get(VALUE self)
563
+ {
564
+ xmlParserCtxtPtr ctxt;
565
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
566
+
567
+ if (ctxt->node == NULL)
568
+ return (Qnil);
569
+ else
570
+ return (rxml_node_wrap(ctxt->node));
571
+ }
572
+
573
+ /*
574
+ * call-seq:
575
+ * context.node_depth_max -> num
576
+ *
577
+ * Obtain the maximum node depth for this context.
578
+ */
579
+ static VALUE rxml_parser_context_node_depth_max_get(VALUE self)
580
+ {
581
+ xmlParserCtxtPtr ctxt;
582
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
583
+
584
+ return (INT2NUM(ctxt->nodeMax));
585
+ }
586
+
587
+ /*
588
+ * call-seq:
589
+ * context.num_chars -> num
590
+ *
591
+ * Obtain the number of characters in this context.
592
+ */
593
+ static VALUE rxml_parser_context_num_chars_get(VALUE self)
594
+ {
595
+ xmlParserCtxtPtr ctxt;
596
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
597
+
598
+ return (LONG2NUM(ctxt->nbChars));
599
+ }
600
+
601
+
602
+ /*
603
+ * call-seq:
604
+ * context.options > XML::Parser::Options::NOENT
605
+ *
606
+ * Returns the parser options for this context. Multiple
607
+ * options can be combined by using Bitwise OR (|).
608
+ */
609
+ static VALUE rxml_parser_context_options_get(VALUE self)
610
+ {
611
+ xmlParserCtxtPtr ctxt;
612
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
613
+
614
+ return INT2NUM(ctxt->options);
615
+ }
616
+
617
+ /*
618
+ * call-seq:
619
+ * context.options = XML::Parser::Options::NOENT |
620
+ XML::Parser::Options::NOCDATA
621
+ *
622
+ * Provides control over the execution of a parser. Valid values
623
+ * are the constants defined on XML::Parser::Options. Multiple
624
+ * options can be combined by using Bitwise OR (|).
625
+ */
626
+ static VALUE rxml_parser_context_options_set(VALUE self, VALUE options)
627
+ {
628
+ xmlParserCtxtPtr ctxt;
629
+ Check_Type(options, T_FIXNUM);
630
+
631
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
632
+ xmlCtxtUseOptions(ctxt, NUM2INT(options));
633
+
634
+ return self;
635
+ }
636
+
637
+ /*
638
+ * call-seq:
639
+ * context.recovery? -> (true|false)
640
+ *
641
+ * Determine whether recovery mode is enabled in this
642
+ * context.
643
+ */
644
+ static VALUE rxml_parser_context_recovery_q(VALUE self)
645
+ {
646
+ xmlParserCtxtPtr ctxt;
647
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
648
+
649
+ if (ctxt->recovery)
650
+ return (Qtrue);
651
+ else
652
+ return (Qfalse);
653
+ }
654
+
655
+ /*
656
+ * call-seq:
657
+ * context.recovery = true|false
658
+ *
659
+ * Control whether recovery mode is enabled in this
660
+ * context.
661
+ */
662
+ static VALUE rxml_parser_context_recovery_set(VALUE self, VALUE value)
663
+ {
664
+ xmlParserCtxtPtr ctxt;
665
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
666
+
667
+ if (value == Qfalse)
668
+ {
669
+ ctxt->recovery = 0;
670
+ return (Qfalse);
671
+ }
672
+ else
673
+ {
674
+ ctxt->recovery = 1;
675
+ return (Qtrue);
676
+ }
677
+ }
678
+
679
+ /*
680
+ * call-seq:
681
+ * context.replace_entities? -> (true|false)
682
+ *
683
+ * Determine whether external entity replacement is enabled in this
684
+ * context.
685
+ */
686
+ static VALUE rxml_parser_context_replace_entities_q(VALUE self)
687
+ {
688
+ xmlParserCtxtPtr ctxt;
689
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
690
+
691
+ if (ctxt->replaceEntities)
692
+ return (Qtrue);
693
+ else
694
+ return (Qfalse);
695
+ }
696
+
697
+ /*
698
+ * call-seq:
699
+ * context.replace_entities = true|false
700
+ *
701
+ * Control whether external entity replacement is enabled in this
702
+ * context.
703
+ */
704
+ static VALUE rxml_parser_context_replace_entities_set(VALUE self, VALUE value)
705
+ {
706
+ xmlParserCtxtPtr ctxt;
707
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
708
+
709
+ if (value == Qfalse)
710
+ {
711
+ ctxt->replaceEntities = 0;
712
+ return (Qfalse);
713
+ }
714
+ else
715
+ {
716
+ ctxt->replaceEntities = 1;
717
+ return (Qtrue);
718
+ }
719
+ }
720
+
721
+ /*
722
+ * call-seq:
723
+ * context.space_depth -> num
724
+ *
725
+ * Obtain the space depth for this context.
726
+ */
727
+ static VALUE rxml_parser_context_space_depth_get(VALUE self)
728
+ {
729
+ xmlParserCtxtPtr ctxt;
730
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
731
+
732
+ return (INT2NUM(ctxt->spaceNr));
733
+ }
734
+
735
+ /*
736
+ * call-seq:
737
+ * context.space_depth -> num
738
+ *
739
+ * Obtain the maximum space depth for this context.
740
+ */
741
+ static VALUE rxml_parser_context_space_depth_max_get(VALUE self)
742
+ {
743
+ xmlParserCtxtPtr ctxt;
744
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
745
+
746
+ return (INT2NUM(ctxt->spaceMax));
747
+ }
748
+
749
+ /*
750
+ * call-seq:
751
+ * context.subset_external? -> (true|false)
752
+ *
753
+ * Determine whether this context is a subset of an
754
+ * external context.
755
+ */
756
+ static VALUE rxml_parser_context_subset_external_q(VALUE self)
757
+ {
758
+ xmlParserCtxtPtr ctxt;
759
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
760
+
761
+ if (ctxt->inSubset == 2)
762
+ return (Qtrue);
763
+ else
764
+ return (Qfalse);
765
+ }
766
+
767
+ /*
768
+ * call-seq:
769
+ * context.subset_internal? -> (true|false)
770
+ *
771
+ * Determine whether this context is a subset of an
772
+ * internal context.
773
+ */
774
+ static VALUE rxml_parser_context_subset_internal_q(VALUE self)
775
+ {
776
+ xmlParserCtxtPtr ctxt;
777
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
778
+
779
+ if (ctxt->inSubset == 1)
780
+ return (Qtrue);
781
+ else
782
+ return (Qfalse);
783
+ }
784
+
785
+ /*
786
+ * call-seq:
787
+ * context.subset_internal_name -> "name"
788
+ *
789
+ * Obtain this context's subset name (valid only if
790
+ * either of subset_external? or subset_internal?
791
+ * is true).
792
+ */
793
+ static VALUE rxml_parser_context_subset_name_get(VALUE self)
794
+ {
795
+ xmlParserCtxtPtr ctxt;
796
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
797
+
798
+ if (ctxt->intSubName == NULL)
799
+ return (Qnil);
800
+ else
801
+ return (rxml_new_cstr(ctxt->intSubName, ctxt->encoding));
802
+ }
803
+
804
+ /*
805
+ * call-seq:
806
+ * context.subset_external_uri -> "uri"
807
+ *
808
+ * Obtain this context's external subset URI. (valid only if
809
+ * either of subset_external? or subset_internal?
810
+ * is true).
811
+ */
812
+ static VALUE rxml_parser_context_subset_external_uri_get(VALUE self)
813
+ {
814
+ xmlParserCtxtPtr ctxt;
815
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
816
+
817
+ if (ctxt->extSubURI == NULL)
818
+ return (Qnil);
819
+ else
820
+ return (rxml_new_cstr( ctxt->extSubURI, ctxt->encoding));
821
+ }
822
+
823
+ /*
824
+ * call-seq:
825
+ * context.subset_external_system_id -> "system_id"
826
+ *
827
+ * Obtain this context's external subset system identifier.
828
+ * (valid only if either of subset_external? or subset_internal?
829
+ * is true).
830
+ */
831
+ static VALUE rxml_parser_context_subset_external_system_id_get(VALUE self)
832
+ {
833
+ xmlParserCtxtPtr ctxt;
834
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
835
+
836
+ if (ctxt->extSubSystem == NULL)
837
+ return (Qnil);
838
+ else
839
+ return (rxml_new_cstr( ctxt->extSubSystem, ctxt->encoding));
840
+ }
841
+
842
+ /*
843
+ * call-seq:
844
+ * context.standalone? -> (true|false)
845
+ *
846
+ * Determine whether this is a standalone context.
847
+ */
848
+ static VALUE rxml_parser_context_standalone_q(VALUE self)
849
+ {
850
+ xmlParserCtxtPtr ctxt;
851
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
852
+
853
+ if (ctxt->standalone)
854
+ return (Qtrue);
855
+ else
856
+ return (Qfalse);
857
+ }
858
+
859
+ /*
860
+ * call-seq:
861
+ * context.stats? -> (true|false)
862
+ *
863
+ * Determine whether this context maintains statistics.
864
+ */
865
+ static VALUE rxml_parser_context_stats_q(VALUE self)
866
+ {
867
+ xmlParserCtxtPtr ctxt;
868
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
869
+
870
+ if (ctxt->record_info)
871
+ return (Qtrue);
872
+ else
873
+ return (Qfalse);
874
+ }
875
+
876
+ /*
877
+ * call-seq:
878
+ * context.valid? -> (true|false)
879
+ *
880
+ * Determine whether this context is valid.
881
+ */
882
+ static VALUE rxml_parser_context_valid_q(VALUE self)
883
+ {
884
+ xmlParserCtxtPtr ctxt;
885
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
886
+
887
+ if (ctxt->valid)
888
+ return (Qtrue);
889
+ else
890
+ return (Qfalse);
891
+ }
892
+
893
+ /*
894
+ * call-seq:
895
+ * context.validate? -> (true|false)
896
+ *
897
+ * Determine whether validation is enabled in this context.
898
+ */
899
+ static VALUE rxml_parser_context_validate_q(VALUE self)
900
+ {
901
+ xmlParserCtxtPtr ctxt;
902
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
903
+
904
+ if (ctxt->validate)
905
+ return (Qtrue);
906
+ else
907
+ return (Qfalse);
908
+ }
909
+
910
+ /*
911
+ * call-seq:
912
+ * context.version -> "version"
913
+ *
914
+ * Obtain this context's version identifier.
915
+ */
916
+ static VALUE rxml_parser_context_version_get(VALUE self)
917
+ {
918
+ xmlParserCtxtPtr ctxt;
919
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
920
+
921
+ if (ctxt->version == NULL)
922
+ return (Qnil);
923
+ else
924
+ return (rxml_new_cstr( ctxt->version, ctxt->encoding));
925
+ }
926
+
927
+ /*
928
+ * call-seq:
929
+ * context.well_formed? -> (true|false)
930
+ *
931
+ * Determine whether this context contains well-formed XML.
932
+ */
933
+ static VALUE rxml_parser_context_well_formed_q(VALUE self)
934
+ {
935
+ xmlParserCtxtPtr ctxt;
936
+ Data_Get_Struct(self, xmlParserCtxt, ctxt);
937
+
938
+ if (ctxt->wellFormed)
939
+ return (Qtrue);
940
+ else
941
+ return (Qfalse);
942
+ }
943
+
944
+ void rxml_init_parser_context(void)
945
+ {
946
+ IO_ATTR = ID2SYM(rb_intern("@io"));
947
+
948
+ cXMLParserContext = rb_define_class_under(cXMLParser, "Context", rb_cObject);
949
+ rb_define_alloc_func(cXMLParserContext, rxml_parser_context_alloc);
950
+
951
+ rb_define_singleton_method(cXMLParserContext, "document", rxml_parser_context_document, 1);
952
+ rb_define_singleton_method(cXMLParserContext, "file", rxml_parser_context_file, 1);
953
+ rb_define_singleton_method(cXMLParserContext, "io", rxml_parser_context_io, 1);
954
+ rb_define_singleton_method(cXMLParserContext, "string", rxml_parser_context_string, 1);
955
+
956
+ rb_define_method(cXMLParserContext, "base_uri", rxml_parser_context_base_uri_get, 0);
957
+ rb_define_method(cXMLParserContext, "base_uri=", rxml_parser_context_base_uri_set, 1);
958
+ rb_define_method(cXMLParserContext, "close", rxml_parser_context_close, 0);
959
+ rb_define_method(cXMLParserContext, "data_directory", rxml_parser_context_data_directory_get, 0);
960
+ rb_define_method(cXMLParserContext, "depth", rxml_parser_context_depth_get, 0);
961
+ rb_define_method(cXMLParserContext, "disable_cdata?", rxml_parser_context_disable_cdata_q, 0);
962
+ rb_define_method(cXMLParserContext, "disable_cdata=", rxml_parser_context_disable_cdata_set, 1);
963
+ rb_define_method(cXMLParserContext, "disable_sax?", rxml_parser_context_disable_sax_q, 0);
964
+ rb_define_method(cXMLParserContext, "docbook?", rxml_parser_context_docbook_q, 0);
965
+ rb_define_method(cXMLParserContext, "encoding", rxml_parser_context_encoding_get, 0);
966
+ rb_define_method(cXMLParserContext, "encoding=", rxml_parser_context_encoding_set, 1);
967
+ rb_define_method(cXMLParserContext, "errno", rxml_parser_context_errno_get, 0);
968
+ rb_define_method(cXMLParserContext, "html?", rxml_parser_context_html_q, 0);
969
+ rb_define_method(cXMLParserContext, "io_max_num_streams", rxml_parser_context_io_max_num_streams_get, 0);
970
+ rb_define_method(cXMLParserContext, "io_num_streams", rxml_parser_context_io_num_streams_get, 0);
971
+ rb_define_method(cXMLParserContext, "keep_blanks?", rxml_parser_context_keep_blanks_q, 0);
972
+ rb_define_method(cXMLParserContext, "name_node", rxml_parser_context_name_node_get, 0);
973
+ rb_define_method(cXMLParserContext, "name_depth", rxml_parser_context_name_depth_get, 0);
974
+ rb_define_method(cXMLParserContext, "name_depth_max", rxml_parser_context_name_depth_max_get, 0);
975
+ rb_define_method(cXMLParserContext, "name_tab", rxml_parser_context_name_tab_get, 0);
976
+ rb_define_method(cXMLParserContext, "node", rxml_parser_context_node_get, 0);
977
+ rb_define_method(cXMLParserContext, "node_depth", rxml_parser_context_node_depth_get, 0);
978
+ rb_define_method(cXMLParserContext, "node_depth_max", rxml_parser_context_node_depth_max_get, 0);
979
+ rb_define_method(cXMLParserContext, "num_chars", rxml_parser_context_num_chars_get, 0);
980
+ rb_define_method(cXMLParserContext, "options", rxml_parser_context_options_get, 0);
981
+ rb_define_method(cXMLParserContext, "options=", rxml_parser_context_options_set, 1);
982
+ rb_define_method(cXMLParserContext, "recovery?", rxml_parser_context_recovery_q, 0);
983
+ rb_define_method(cXMLParserContext, "recovery=", rxml_parser_context_recovery_set, 1);
984
+ rb_define_method(cXMLParserContext, "replace_entities?", rxml_parser_context_replace_entities_q, 0);
985
+ rb_define_method(cXMLParserContext, "replace_entities=", rxml_parser_context_replace_entities_set, 1);
986
+ rb_define_method(cXMLParserContext, "space_depth", rxml_parser_context_space_depth_get, 0);
987
+ rb_define_method(cXMLParserContext, "space_depth_max", rxml_parser_context_space_depth_max_get, 0);
988
+ rb_define_method(cXMLParserContext, "subset_external?", rxml_parser_context_subset_external_q, 0);
989
+ rb_define_method(cXMLParserContext, "subset_external_system_id", rxml_parser_context_subset_external_system_id_get, 0);
990
+ rb_define_method(cXMLParserContext, "subset_external_uri", rxml_parser_context_subset_external_uri_get, 0);
991
+ rb_define_method(cXMLParserContext, "subset_internal?", rxml_parser_context_subset_internal_q, 0);
992
+ rb_define_method(cXMLParserContext, "subset_internal_name", rxml_parser_context_subset_name_get, 0);
993
+ rb_define_method(cXMLParserContext, "stats?", rxml_parser_context_stats_q, 0);
994
+ rb_define_method(cXMLParserContext, "standalone?", rxml_parser_context_standalone_q, 0);
995
+ rb_define_method(cXMLParserContext, "valid", rxml_parser_context_valid_q, 0);
996
+ rb_define_method(cXMLParserContext, "validate?", rxml_parser_context_validate_q, 0);
997
+ rb_define_method(cXMLParserContext, "version", rxml_parser_context_version_get, 0);
998
+ rb_define_method(cXMLParserContext, "well_formed?", rxml_parser_context_well_formed_q, 0);
999
+ }