libxml-ruby 2.8.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY +15 -0
  3. data/README.rdoc +7 -7
  4. data/Rakefile +80 -78
  5. data/ext/libxml/extconf.h +4 -0
  6. data/ext/libxml/extconf.rb +57 -116
  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 +14 -15
  29. data/ext/libxml/ruby_xml_xpath.c +188 -188
  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 +47 -11
  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
@@ -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
+ }