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

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