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,1228 +1,1226 @@
1
- /* Copyright (c) 2006-2007 Apple Inc.
2
- * Please see the LICENSE file for copyright and distribution information. */
3
-
4
- #include "ruby_libxml.h"
5
- #include "ruby_xml_reader.h"
6
-
7
- /*
8
- * Document-class: LibXML::XML::Reader
9
- *
10
- * The XML::Reader class provides a simpler, alternative way of parsing an XML
11
- * document in contrast to XML::Parser or XML::SaxParser. A XML::Reader instance
12
- * acts like a cursor going forward in a document stream, stopping at each node
13
- * it encounters. To advance to the next node, simply cadd XML::Reader#read.
14
- *
15
- * The XML::Reader API closely matches the DOM Core specification and supports
16
- * namespaces, xml:base, entity handling and DTDs.
17
- *
18
- * To summarize, XML::Reader provides a far simpler API to use versus XML::SaxParser
19
- * and is more memory efficient than using XML::Parser to create a DOM tree.
20
- *
21
- * Example:
22
- *
23
- * reader = XML::Reader.string("<foo><bar>1</bar><bar>2</bar><bar>3</bar></foo>")
24
- * reader.read
25
- * assert_equal('foo', reader.name)
26
- * assert_equal(nil, reader.value)
27
- *
28
- * 3.times do |i|
29
- * reader.read
30
- * assert_equal(XML::Reader::TYPE_ELEMENT, reader.node_type)
31
- * assert_equal('bar', reader.name)
32
- * reader.read
33
- * assert_equal(XML::Reader::TYPE_TEXT, reader.node_type)
34
- * assert_equal((i + 1).to_s, reader.value)
35
- * reader.read
36
- * assert_equal(XML::Reader::TYPE_END_ELEMENT, reader.node_type)
37
- * end
38
- *
39
- * You can also parse documents (see XML::Reader.document),
40
- * strings (see XML::Parser.string) and io objects (see
41
- * XML::Parser.io).
42
- *
43
- * For a more in depth tutorial, albeit in C, see http://xmlsoft.org/xmlreader.html.*/
44
-
45
-
46
- /* NOTE - We need to wrap the readers document to support Reader.read.node.find('/').
47
- To do this we need to use xmlTextReaderCurrentDoc which means we have to free the
48
- document ourselves. Annoying... */
49
-
50
- VALUE cXMLReader;
51
-
52
- static ID BASE_URI_SYMBOL;
53
- static ID ENCODING_SYMBOL;
54
- static ID IO_ATTR;
55
- static ID OPTIONS_SYMBOL;
56
-
57
- static void rxml_reader_free(xmlTextReaderPtr xreader)
58
- {
59
- xmlFreeTextReader(xreader);
60
- }
61
-
62
- static void rxml_reader_mark(xmlTextReaderPtr xreader)
63
- {
64
- xmlDocPtr xdoc = xmlTextReaderCurrentDoc(xreader);
65
-
66
- if (xdoc && xdoc->_private)
67
- rb_gc_mark((VALUE) xdoc->_private);
68
- }
69
-
70
- static VALUE rxml_reader_wrap(xmlTextReaderPtr xreader)
71
- {
72
- return Data_Wrap_Struct(cXMLReader, NULL, rxml_reader_free, xreader);
73
- }
74
-
75
-
76
- static xmlTextReaderPtr rxml_text_reader_get(VALUE obj)
77
- {
78
- xmlTextReaderPtr xreader;
79
- Data_Get_Struct(obj, xmlTextReader, xreader);
80
- return xreader;
81
- }
82
-
83
- /*
84
- * call-seq:
85
- * XML::Reader.document(doc) -> XML::Reader
86
- *
87
- * Create an new reader for the specified document.
88
- */
89
- VALUE rxml_reader_document(VALUE klass, VALUE doc)
90
- {
91
- xmlDocPtr xdoc;
92
- xmlTextReaderPtr xreader;
93
-
94
- Data_Get_Struct(doc, xmlDoc, xdoc);
95
-
96
- xreader = xmlReaderWalker(xdoc);
97
-
98
- if (xreader == NULL)
99
- rxml_raise(&xmlLastError);
100
-
101
- return rxml_reader_wrap(xreader);
102
- }
103
-
104
- /* call-seq:
105
- * XML::Reader.file(path) -> XML::Reader
106
- * XML::Reader.file(path, :encoding => XML::Encoding::UTF_8,
107
- * :options => XML::Parser::Options::NOENT) -> XML::Parser
108
- *
109
- * Creates a new reader by parsing the specified file or uri.
110
- *
111
- * You may provide an optional hash table to control how the
112
- * parsing is performed. Valid options are:
113
- *
114
- * encoding - The document encoding, defaults to nil. Valid values
115
- * are the encoding constants defined on XML::Encoding.
116
- * options - Controls the execution of the parser, defaults to 0.
117
- * Valid values are the constants defined on
118
- * XML::Parser::Options. Mutliple options can be combined
119
- * by using Bitwise OR (|).
120
- */
121
- static VALUE rxml_reader_file(int argc, VALUE *argv, VALUE klass)
122
- {
123
- xmlTextReaderPtr xreader;
124
- VALUE path;
125
- VALUE options;
126
-
127
- const char *xencoding = NULL;
128
- int xoptions = 0;
129
-
130
- rb_scan_args(argc, argv, "11", &path, &options);
131
- Check_Type(path, T_STRING);
132
-
133
- if (!NIL_P(options))
134
- {
135
- VALUE encoding = Qnil;
136
- VALUE parserOptions = Qnil;
137
-
138
- Check_Type(options, T_HASH);
139
-
140
- encoding = rb_hash_aref(options, BASE_URI_SYMBOL);
141
- xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
142
-
143
- parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
144
- xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
145
- }
146
-
147
- xreader = xmlReaderForFile(StringValueCStr(path), xencoding, xoptions);
148
-
149
- if (xreader == NULL)
150
- rxml_raise(&xmlLastError);
151
-
152
- return rxml_reader_wrap(xreader);
153
- }
154
-
155
- /* call-seq:
156
- * XML::Reader.io(io) -> XML::Reader
157
- * XML::Reader.io(io, :encoding => XML::Encoding::UTF_8,
158
- * :options => XML::Parser::Options::NOENT) -> XML::Parser
159
- *
160
- * Creates a new reader by parsing the specified io object.
161
- *
162
- * You may provide an optional hash table to control how the
163
- * parsing is performed. Valid options are:
164
- *
165
- * base_uri - The base url for the parsed document.
166
- * encoding - The document encoding, defaults to nil. Valid values
167
- * are the encoding constants defined on XML::Encoding.
168
- * options - Controls the execution of the parser, defaults to 0.
169
- * Valid values are the constants defined on
170
- * XML::Parser::Options. Mutliple options can be combined
171
- * by using Bitwise OR (|).
172
- */
173
- static VALUE rxml_reader_io(int argc, VALUE *argv, VALUE klass)
174
- {
175
- xmlTextReaderPtr xreader;
176
- VALUE result;
177
- VALUE io;
178
- VALUE options;
179
- char *xbaseurl = NULL;
180
- const char *xencoding = NULL;
181
- int xoptions = 0;
182
-
183
- rb_scan_args(argc, argv, "11", &io, &options);
184
-
185
- if (!NIL_P(options))
186
- {
187
- VALUE baseurl = Qnil;
188
- VALUE encoding = Qnil;
189
- VALUE parserOptions = Qnil;
190
-
191
- Check_Type(options, T_HASH);
192
-
193
- baseurl = rb_hash_aref(options, BASE_URI_SYMBOL);
194
- xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl);
195
-
196
- encoding = rb_hash_aref(options, ENCODING_SYMBOL);
197
- xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
198
-
199
- parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
200
- xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
201
- }
202
-
203
- xreader = xmlReaderForIO((xmlInputReadCallback) rxml_read_callback, NULL,
204
- (void *) io,
205
- xbaseurl, xencoding, xoptions);
206
-
207
- if (xreader == NULL)
208
- rxml_raise(&xmlLastError);
209
-
210
- result = rxml_reader_wrap(xreader);
211
-
212
- /* Attach io object to parser so it won't get freed.*/
213
- rb_ivar_set(result, IO_ATTR, io);
214
-
215
- return result;
216
- }
217
-
218
- /* call-seq:
219
- * XML::Reader.string(io) -> XML::Reader
220
- * XML::Reader.string(io, :encoding => XML::Encoding::UTF_8,
221
- * :options => XML::Parser::Options::NOENT) -> XML::Parser
222
- *
223
- * Creates a new reader by parsing the specified string.
224
- *
225
- * You may provide an optional hash table to control how the
226
- * parsing is performed. Valid options are:
227
- *
228
- * base_uri - The base url for the parsed document.
229
- * encoding - The document encoding, defaults to nil. Valid values
230
- * are the encoding constants defined on XML::Encoding.
231
- * options - Controls the execution of the parser, defaults to 0.
232
- * Valid values are the constants defined on
233
- * XML::Parser::Options. Mutliple options can be combined
234
- * by using Bitwise OR (|).
235
- */
236
- static VALUE rxml_reader_string(int argc, VALUE *argv, VALUE klass)
237
- {
238
- xmlTextReaderPtr xreader;
239
- VALUE string;
240
- VALUE options;
241
- char *xbaseurl = NULL;
242
- const char *xencoding = NULL;
243
- int xoptions = 0;
244
-
245
- rb_scan_args(argc, argv, "11", &string, &options);
246
- Check_Type(string, T_STRING);
247
-
248
- if (!NIL_P(options))
249
- {
250
- VALUE baseurl = Qnil;
251
- VALUE encoding = Qnil;
252
- VALUE parserOptions = Qnil;
253
-
254
- Check_Type(options, T_HASH);
255
-
256
- baseurl = rb_hash_aref(options, BASE_URI_SYMBOL);
257
- xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl);
258
-
259
- encoding = rb_hash_aref(options, ENCODING_SYMBOL);
260
- xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
261
-
262
- parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
263
- xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
264
- }
265
-
266
- xreader = xmlReaderForMemory(StringValueCStr(string), RSTRING_LEN(string),
267
- xbaseurl, xencoding, xoptions);
268
-
269
- if (xreader == NULL)
270
- rxml_raise(&xmlLastError);
271
-
272
- return rxml_reader_wrap(xreader);
273
- }
274
-
275
- /*
276
- * call-seq:
277
- * reader.close -> code
278
- *
279
- * This method releases any resources allocated by the current instance
280
- * changes the state to Closed and close any underlying input.
281
- */
282
- static VALUE rxml_reader_close(VALUE self)
283
- {
284
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
285
- return INT2FIX(xmlTextReaderClose(xreader));
286
- }
287
-
288
- /*
289
- * call-seq:
290
- * reader.move_to_attribute_no(index) -> code
291
- *
292
- * Move the position of the current instance to the attribute with the
293
- * specified index relative to the containing element.
294
- */
295
- static VALUE rxml_reader_move_to_attr_no(VALUE self, VALUE index)
296
- {
297
- int ret;
298
- xmlTextReaderPtr xreader;
299
-
300
- xreader = rxml_text_reader_get(self);
301
- ret = xmlTextReaderMoveToAttributeNo(xreader, FIX2INT(index));
302
-
303
- return INT2FIX(ret);
304
- }
305
-
306
- /*
307
- * call-seq:
308
- * reader.move_to_attribute(localName) -> code
309
- *
310
- * Move the position of the current instance to the attribute with the
311
- * specified name relative to the containing element.
312
- */
313
- static VALUE rxml_reader_move_to_attr(VALUE self, VALUE val)
314
- {
315
- if (TYPE(val) == T_FIXNUM)
316
- {
317
- rb_warn("%s::move_to_attribute with a Fixnum argument is deprecated. "
318
- "Please, consider move_to_attribute_no method instead.",
319
- rb_class2name(cXMLReader));
320
- return rxml_reader_move_to_attr_no(self, val);
321
- }
322
- else
323
- {
324
- int ret;
325
- xmlTextReaderPtr xreader;
326
-
327
- xreader = rxml_text_reader_get(self);
328
- ret = xmlTextReaderMoveToAttribute(xreader,
329
- (const xmlChar *) StringValueCStr(val));
330
-
331
- return INT2FIX(ret);
332
- }
333
- }
334
-
335
- /*
336
- * call-seq:
337
- * reader.move_to_attribute_ns(localName, namespaceURI) -> code
338
- *
339
- * Move the position of the current instance to the attribute with the
340
- * specified name and namespace relative to the containing element.
341
- */
342
- static VALUE rxml_reader_move_to_attr_ns(VALUE self, VALUE name, VALUE ns)
343
- {
344
- int ret;
345
- xmlTextReaderPtr xreader;
346
-
347
- xreader = rxml_text_reader_get(self);
348
- ret = xmlTextReaderMoveToAttributeNs(xreader,
349
- (const xmlChar *) StringValueCStr(name),
350
- (const xmlChar *) StringValueCStr(ns));
351
-
352
- return INT2FIX(ret);
353
- }
354
-
355
- /*
356
- * call-seq:
357
- * reader.move_to_first_attribute -> code
358
- *
359
- * Move the position of the current instance to the first attribute associated
360
- * with the current node.
361
- */
362
- static VALUE rxml_reader_move_to_first_attr(VALUE self)
363
- {
364
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
365
- return INT2FIX(xmlTextReaderMoveToFirstAttribute(xreader));
366
- }
367
-
368
- /*
369
- * call-seq:
370
- * reader.move_to_next_attribute -> code
371
- *
372
- * Move the position of the current instance to the next attribute associated
373
- * with the current node.
374
- */
375
- static VALUE rxml_reader_move_to_next_attr(VALUE self)
376
- {
377
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
378
- return INT2FIX(xmlTextReaderMoveToNextAttribute(xreader));
379
- }
380
-
381
- /*
382
- * call-seq:
383
- * reader.move_to_element -> code
384
- *
385
- * Move the position of the current instance to the node that contains the
386
- * current attribute node.
387
- */
388
- static VALUE rxml_reader_move_to_element(VALUE self)
389
- {
390
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
391
- return INT2FIX(xmlTextReaderMoveToElement(xreader));
392
- }
393
-
394
- /*
395
- * call-seq:
396
- * reader.next -> code
397
- *
398
- * Skip to the node following the current one in document order while avoiding
399
- * the subtree if any.
400
- */
401
- static VALUE rxml_reader_next(VALUE self)
402
- {
403
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
404
- return INT2FIX(xmlTextReaderNext(xreader));
405
- }
406
-
407
- /*
408
- * call-seq:
409
- * reader.next_sibling -> code
410
- *
411
- * Skip to the node following the current one in document order while avoiding
412
- * the subtree if any. Currently implemented only for Readers built on a
413
- * document.
414
- */
415
- static VALUE rxml_reader_next_sibling(VALUE self)
416
- {
417
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
418
- return INT2FIX(xmlTextReaderNextSibling(xreader));
419
- }
420
-
421
- /*
422
- * call-seq:
423
- * reader.node -> XML::Node
424
- *
425
- * Returns the reader's current node. It will return
426
- * nil if Reader#read has not yet been called.
427
- * WARNING - Using this method is dangerous because the
428
- * the node may be destroyed on the next #read.
429
- */
430
- static VALUE rxml_reader_node(VALUE self)
431
- {
432
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
433
- xmlNodePtr xnode = xmlTextReaderCurrentNode(xreader);
434
- return xnode ? rxml_node_wrap(xnode) : Qnil;
435
- }
436
-
437
- /*
438
- * call-seq:
439
- * reader.node_type -> type
440
- *
441
- * Get the node type of the current node. Reference:
442
- * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
443
- */
444
- static VALUE rxml_reader_node_type(VALUE self)
445
- {
446
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
447
- return INT2FIX(xmlTextReaderNodeType(xreader));
448
- }
449
-
450
- /*
451
- * call-seq:
452
- * reader.normalization -> value
453
- *
454
- * The value indicating whether to normalize white space and attribute values.
455
- * Since attribute value and end of line normalizations are a MUST in the XML
456
- * specification only the value true is accepted. The broken bahaviour of
457
- * accepting out of range character entities like &#0; is of course not
458
- * supported either.
459
- *
460
- * Return 1 or -1 in case of error.
461
- */
462
- static VALUE rxml_reader_normalization(VALUE self)
463
- {
464
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
465
- return INT2FIX(xmlTextReaderNormalization(xreader));
466
- }
467
-
468
- /*
469
- * call-seq:
470
- * reader.read -> nil|true|false
471
- *
472
- * Causes the reader to move to the next node in the stream, exposing its properties.
473
- *
474
- * Returns true if a node was successfully read or false if there are no more
475
- * nodes to read. On errors, an exception is raised.*/
476
- static VALUE rxml_reader_read(VALUE self)
477
- {
478
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
479
- int result = xmlTextReaderRead(xreader);
480
- switch(result)
481
- {
482
- case -1:
483
- rxml_raise(&xmlLastError);
484
- return Qnil;
485
- break;
486
- case 0:
487
- return Qfalse;
488
- case 1:
489
- return Qtrue;
490
- default:
491
- rb_raise(rb_eRuntimeError,
492
- "xmlTextReaderRead did not return -1, 0 or 1. Return value was: %d", result);
493
- }
494
- }
495
-
496
- /*
497
- * call-seq:
498
- * reader.read_attribute_value -> code
499
- *
500
- * Parse an attribute value into one or more Text and EntityReference nodes.
501
- *
502
- * Return 1 in case of success, 0 if the reader was not positionned on an
503
- * attribute node or all the attribute values have been read, or -1 in case of
504
- * error.
505
- */
506
- static VALUE rxml_reader_read_attr_value(VALUE self)
507
- {
508
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
509
- return INT2FIX(xmlTextReaderReadAttributeValue(xreader));
510
- }
511
-
512
- /*
513
- * call-seq:
514
- * reader.read_inner_xml -> data
515
- *
516
- * Read the contents of the current node, including child nodes and markup.
517
- *
518
- * Return a string containing the XML content, or nil if the current node is
519
- * neither an element nor attribute, or has no child nodes.
520
- */
521
- static VALUE rxml_reader_read_inner_xml(VALUE self)
522
- {
523
- VALUE result = Qnil;
524
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
525
-
526
- xmlChar *xml = xmlTextReaderReadInnerXml(xReader);
527
-
528
- if (xml)
529
- {
530
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
531
- result = rxml_new_cstr((const char*) xml, xencoding);
532
- xmlFree(xml);
533
- }
534
-
535
- return result;
536
- }
537
-
538
- /*
539
- * call-seq:
540
- * reader.read_outer_xml -> data
541
- *
542
- * Read the contents of the current node, including child nodes and markup.
543
- *
544
- * Return a string containing the XML content, or nil if the current node is
545
- * neither an element nor attribute, or has no child nodes.
546
- */
547
- static VALUE rxml_reader_read_outer_xml(VALUE self)
548
- {
549
- VALUE result = Qnil;
550
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
551
-
552
- xmlChar *xml = xmlTextReaderReadOuterXml(xReader);
553
-
554
- if (xml)
555
- {
556
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
557
- result = rxml_new_cstr((const char*) xml, xencoding);
558
- xmlFree(xml);
559
- }
560
-
561
- return result;
562
- }
563
-
564
- /*
565
- * call-seq:
566
- * reader.read_state -> state
567
- *
568
- * Get the read state of the reader.
569
- */
570
- static VALUE rxml_reader_read_state(VALUE self)
571
- {
572
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
573
- return INT2FIX(xmlTextReaderReadState(xreader));
574
- }
575
-
576
- /*
577
- * call-seq:
578
- * reader.read_string -> string
579
- *
580
- * Read the contents of an element or a text node as a string.
581
- *
582
- * Return a string containing the contents of the Element or Text node, or nil
583
- * if the reader is positioned on any other type of node.
584
- */
585
- static VALUE rxml_reader_read_string(VALUE self)
586
- {
587
- VALUE result = Qnil;
588
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
589
-
590
- xmlChar *xml = xmlTextReaderReadString(xReader);
591
-
592
- if (xml)
593
- {
594
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
595
- result = rxml_new_cstr((const char*) xml, xencoding);
596
- xmlFree(xml);
597
- }
598
-
599
- return result;
600
- }
601
-
602
- /*
603
- * call-seq:
604
- * reader.relax_ng_validate(rng) -> boolean
605
- *
606
- * Use RelaxNG to validate the document as it is processed. Activation is only
607
- * possible before the first read. If +rng+ is nil, the RelaxNG validation is
608
- * desactivated.
609
- *
610
- * Return true in case the RelaxNG validation could be (des)activated and false in
611
- * case of error.
612
- */
613
- static VALUE rxml_reader_relax_ng_validate(VALUE self, VALUE rng)
614
- {
615
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
616
- xmlRelaxNGPtr xrelax;
617
- int status;
618
- Data_Get_Struct(rng, xmlRelaxNG, xrelax);
619
-
620
- status = xmlTextReaderRelaxNGSetSchema(xreader, xrelax);
621
- return (status == 0 ? Qtrue : Qfalse);
622
- }
623
-
624
- #if LIBXML_VERSION >= 20620
625
- /*
626
- * call-seq:
627
- * reader.schema_validate(schema) -> boolean
628
- *
629
- * Use W3C XSD schema to validate the document as it is processed. Activation
630
- * is only possible before the first read. If +schema+ is nil, then XML Schema
631
- * validation is deactivated.
632
- *
633
- * Return false if if the schema's validation could be (de)activated and true
634
- * otherwise.
635
- */
636
- static VALUE
637
- rxml_reader_schema_validate(VALUE self, VALUE xsd)
638
- {
639
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
640
- xmlSchemaPtr xschema;
641
- int status;
642
-
643
- Data_Get_Struct(xsd, xmlSchema, xschema);
644
- status = xmlTextReaderSetSchema(xreader, xschema);
645
- return (status == 0 ? Qtrue : Qfalse);
646
- }
647
- #endif
648
-
649
- /*
650
- * call-seq:
651
- * reader.name -> name
652
- *
653
- * Return the qualified name of the node.
654
- */
655
- static VALUE rxml_reader_name(VALUE self)
656
- {
657
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
658
- const xmlChar *result = xmlTextReaderConstName(xReader);
659
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
660
-
661
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
662
- }
663
-
664
- /*
665
- * call-seq:
666
- * reader.local_name -> name
667
- *
668
- * Return the local name of the node.
669
- */
670
- static VALUE rxml_reader_local_name(VALUE self)
671
- {
672
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
673
- const xmlChar *result = xmlTextReaderConstLocalName(xReader);
674
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
675
-
676
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
677
- }
678
-
679
- /*
680
- * call-seq:
681
- * reader.attribute_count -> count
682
- *
683
- * Provide the number of attributes of the current node.
684
- */
685
- static VALUE rxml_reader_attr_count(VALUE self)
686
- {
687
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
688
- return INT2FIX(xmlTextReaderAttributeCount(xreader));
689
- }
690
-
691
- /*
692
- * call-seq:
693
- * reader.encoding -> XML::Encoding::UTF_8
694
- *
695
- * Returns the encoding of the document being read. Note you
696
- * first have to read data from the reader for encoding
697
- * to return a value
698
- *
699
- * reader = XML::Reader.file(XML_FILE)
700
- * assert_nil(reader.encoding)
701
- * reader.read
702
- * assert_equal(XML::Encoding::UTF_8, reader.encoding)
703
- *
704
- * In addition, libxml always appears to return nil for the encoding
705
- * when parsing strings.
706
- */
707
- static VALUE rxml_reader_encoding(VALUE self)
708
- {
709
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
710
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xreader);
711
- if (xencoding)
712
- return INT2NUM(xmlParseCharEncoding(xencoding));
713
- else
714
- return INT2NUM(XML_CHAR_ENCODING_NONE);
715
- }
716
-
717
- /*
718
- * call-seq:
719
- * reader.base_uri -> URI
720
- *
721
- * Determine the base URI of the node.
722
- */
723
- static VALUE rxml_reader_base_uri(VALUE self)
724
- {
725
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
726
- const xmlChar *result = xmlTextReaderConstBaseUri(xReader);
727
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
728
-
729
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
730
- }
731
-
732
- /*
733
- * call-seq:
734
- * reader.namespace_uri -> URI
735
- *
736
- * Determine the namespace URI of the node.
737
- */
738
- static VALUE rxml_reader_namespace_uri(VALUE self)
739
- {
740
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
741
- const xmlChar *result = xmlTextReaderConstNamespaceUri(xReader);
742
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
743
-
744
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
745
- }
746
-
747
- /*
748
- * call-seq:
749
- * reader.value -> text
750
- *
751
- * Provide the text value of the node if present.
752
- */
753
- static VALUE rxml_reader_value(VALUE self)
754
- {
755
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
756
- const xmlChar *result = xmlTextReaderConstValue(xReader);
757
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
758
-
759
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
760
- }
761
-
762
- /*
763
- * call-seq:
764
- * reader.prefix -> prefix
765
- *
766
- * Get a shorthand reference to the namespace associated with the node.
767
- */
768
- static VALUE rxml_reader_prefix(VALUE self)
769
- {
770
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
771
- const xmlChar *result = xmlTextReaderConstPrefix(xReader);
772
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
773
-
774
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
775
- }
776
-
777
- /*
778
- * call-seq:
779
- * reader.depth -> depth
780
- *
781
- * Get the depth of the node in the tree.
782
- */
783
- static VALUE rxml_reader_depth(VALUE self)
784
- {
785
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
786
- return INT2FIX(xmlTextReaderDepth(xreader));
787
- }
788
-
789
- /*
790
- * call-seq:
791
- * reader.quote_char -> char
792
- *
793
- * Get the quotation mark character used to enclose the value of an attribute,
794
- * as an integer value (and -1 in case of error).
795
- */
796
- static VALUE rxml_reader_quote_char(VALUE self)
797
- {
798
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
799
- return INT2FIX(xmlTextReaderQuoteChar(xreader));
800
- }
801
-
802
- /*
803
- * call-seq:
804
- * reader.standalone -> code
805
- *
806
- * Determine the standalone status of the document being read.
807
- *
808
- * Return 1 if the document was declared to be standalone, 0 if it was
809
- * declared to be not standalone, or -1 if the document did not specify its
810
- * standalone status or in case of error.
811
- */
812
- static VALUE rxml_reader_standalone(VALUE self)
813
- {
814
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
815
- return INT2FIX(xmlTextReaderStandalone(xreader));
816
- }
817
-
818
- /*
819
- * call-seq:
820
- * reader.xml_lang -> value
821
- *
822
- * Get the xml:lang scope within which the node resides.
823
- */
824
- static VALUE rxml_reader_xml_lang(VALUE self)
825
- {
826
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
827
- const xmlChar *result = xmlTextReaderConstXmlLang(xReader);
828
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
829
-
830
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
831
- }
832
-
833
- /*
834
- * call-seq:
835
- * reader.xml_version -> version
836
- *
837
- * Determine the XML version of the document being read.
838
- */
839
- static VALUE rxml_reader_xml_version(VALUE self)
840
- {
841
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
842
- const xmlChar *result = xmlTextReaderConstXmlVersion(xReader);
843
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
844
-
845
- return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
846
- }
847
-
848
- /*
849
- * call-seq:
850
- * reader.has_attributes? -> bool
851
- *
852
- * Get whether the node has attributes.
853
- */
854
- static VALUE rxml_reader_has_attributes(VALUE self)
855
- {
856
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
857
- return xmlTextReaderHasAttributes(xreader) ? Qtrue : Qfalse;
858
- }
859
-
860
- /*
861
- * call-seq:
862
- * reader.has_value? -> bool
863
- *
864
- * Get whether the node can have a text value.
865
- */
866
- static VALUE rxml_reader_has_value(VALUE self)
867
- {
868
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
869
- return xmlTextReaderHasValue(xreader) ? Qtrue : Qfalse;
870
- }
871
-
872
- /*
873
- * call-seq:
874
- * reader[key] -> value
875
- *
876
- * Provide the value of the attribute with the specified index (if +key+ is an
877
- * integer) or with the specified name (if +key+ is a string) relative to the
878
- * containing element, as a string.
879
- */
880
- static VALUE rxml_reader_attribute(VALUE self, VALUE key)
881
- {
882
- VALUE result = Qnil;
883
- xmlChar *xattr;
884
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
885
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
886
-
887
- if (TYPE(key) == T_FIXNUM)
888
- {
889
- xattr = xmlTextReaderGetAttributeNo(xReader, FIX2INT(key));
890
- }
891
- else
892
- {
893
- xattr = xmlTextReaderGetAttribute(xReader, (const xmlChar *) StringValueCStr(key));
894
- }
895
-
896
- if (xattr)
897
- {
898
- result = rxml_new_cstr(xattr, xencoding);
899
- xmlFree(xattr);
900
- }
901
- return result;
902
- }
903
-
904
- /*
905
- * call-seq:
906
- * reader.get_attribute(localName) -> value
907
- *
908
- * Provide the value of the attribute with the specified name
909
- * relative to the containing element.
910
- */
911
- static VALUE rxml_reader_get_attribute(VALUE self, VALUE name)
912
- {
913
- VALUE result = Qnil;
914
- xmlChar *xattr;
915
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
916
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
917
-
918
- xattr = xmlTextReaderGetAttribute(xReader,
919
- (const xmlChar *) StringValueCStr(name));
920
- if (xattr)
921
- {
922
- result = rxml_new_cstr(xattr, xencoding);
923
- xmlFree(xattr);
924
- }
925
- return result;
926
- }
927
-
928
- /*
929
- * call-seq:
930
- * reader.get_attribute_no(index) -> value
931
- *
932
- * Provide the value of the attribute with the specified index
933
- * relative to the containing element.
934
- */
935
- static VALUE rxml_reader_get_attribute_no(VALUE self, VALUE index)
936
- {
937
- VALUE result = Qnil;
938
- xmlChar *xattr;
939
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
940
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
941
-
942
- xattr = xmlTextReaderGetAttributeNo(xReader, FIX2INT(index));
943
- if (xattr)
944
- {
945
- result = rxml_new_cstr(xattr, xencoding);
946
- xmlFree(xattr);
947
- }
948
- return result;
949
- }
950
-
951
- static VALUE rxml_reader_get_attribute_ns(VALUE self, VALUE name, VALUE ns)
952
- {
953
- VALUE result = Qnil;
954
- xmlChar *xattr;
955
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
956
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
957
-
958
- xattr = xmlTextReaderGetAttributeNs(xReader,
959
- (const xmlChar *) StringValueCStr(name),
960
- (const xmlChar *) StringValueCStr(ns));
961
- if (xattr)
962
- {
963
- result = rxml_new_cstr(xattr, xencoding);
964
- xmlFree(xattr);
965
- }
966
- return result;
967
- }
968
-
969
- /*
970
- * call-seq:
971
- * reader.lookup_namespace(prefix) -> value
972
- *
973
- * Resolve a namespace prefix in the scope of the current element.
974
- * To return the default namespace, specify nil as +prefix+.
975
- */
976
- static VALUE rxml_reader_lookup_namespace(VALUE self, VALUE prefix)
977
- {
978
- VALUE result = Qnil;
979
- xmlTextReaderPtr xReader = rxml_text_reader_get(self);
980
- const xmlChar *xnamespace = xmlTextReaderLookupNamespace(xReader, (const xmlChar *) StringValueCStr(prefix));
981
- const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
982
-
983
- if (xnamespace)
984
- {
985
- result = rxml_new_cstr((const char*)xnamespace, (const char*)xencoding);
986
- xmlFree((void *)xnamespace);
987
- }
988
- return result;
989
- }
990
-
991
- /*
992
- * call-seq:
993
- * reader.expand -> node
994
- *
995
- * Returns the current node and its full subtree. Note the returned node
996
- * is valid ONLY until the next read call.
997
- */
998
- static VALUE rxml_reader_expand(VALUE self)
999
- {
1000
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1001
- xmlNodePtr xnode = NULL;
1002
-
1003
- /* At this point we need to wrap the reader's document as explained above. */
1004
- xmlDocPtr xdoc = xmlTextReaderCurrentDoc(xreader);
1005
-
1006
- if (!xdoc)
1007
- rb_raise(rb_eRuntimeError, "The reader does not have a document. Did you forget to call read?");
1008
-
1009
- rxml_document_wrap(xdoc);
1010
-
1011
- /* And now hook in a mark function */
1012
- RDATA(self)->dmark = (RUBY_DATA_FUNC)rxml_reader_mark;
1013
-
1014
- xnode = xmlTextReaderExpand(xreader);
1015
-
1016
- if (!xnode)
1017
- {
1018
- return Qnil;
1019
- }
1020
- else
1021
- {
1022
- return rxml_node_wrap(xnode);
1023
- }
1024
- }
1025
-
1026
- #if LIBXML_VERSION >= 20618
1027
- /*
1028
- * call-seq:
1029
- * reader.byte_consumed -> value
1030
- *
1031
- * This method provides the current index of the parser used by the reader,
1032
- * relative to the start of the current entity.
1033
- */
1034
- static VALUE
1035
- rxml_reader_byte_consumed(VALUE self)
1036
- {
1037
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1038
- return INT2NUM(xmlTextReaderByteConsumed(xreader));
1039
- }
1040
- #endif
1041
-
1042
- #if LIBXML_VERSION >= 20617
1043
- /*
1044
- * call-seq:
1045
- * reader.column_number -> number
1046
- *
1047
- * Provide the column number of the current parsing point.
1048
- */
1049
- static VALUE
1050
- rxml_reader_column_number(VALUE self)
1051
- {
1052
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1053
- return INT2NUM(xmlTextReaderGetParserColumnNumber(xreader));
1054
- }
1055
-
1056
- /*
1057
- * call-seq:
1058
- * reader.line_number -> number
1059
- *
1060
- * Provide the line number of the current parsing point.
1061
- */
1062
- static VALUE
1063
- rxml_reader_line_number(VALUE self)
1064
- {
1065
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1066
- return INT2NUM(xmlTextReaderGetParserLineNumber(xreader));
1067
- }
1068
- #endif
1069
-
1070
- /*
1071
- * call-seq:
1072
- * reader.default? -> bool
1073
- *
1074
- * Return whether an Attribute node was generated from the default value
1075
- * defined in the DTD or schema.
1076
- */
1077
- static VALUE rxml_reader_default(VALUE self)
1078
- {
1079
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1080
- return xmlTextReaderIsDefault(xreader) ? Qtrue : Qfalse;
1081
- }
1082
-
1083
- /*
1084
- * call-seq:
1085
- * reader.namespace_declaration? -> bool
1086
- *
1087
- * Determine whether the current node is a namespace declaration rather than a
1088
- * regular attribute.
1089
- */
1090
- static VALUE rxml_reader_namespace_declaration(VALUE self)
1091
- {
1092
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1093
- return xmlTextReaderIsNamespaceDecl(xreader) ? Qtrue : Qfalse;
1094
- }
1095
-
1096
- /*
1097
- * call-seq:
1098
- * reader.empty_element? -> bool
1099
- *
1100
- * Check if the current node is empty.
1101
- */
1102
- static VALUE rxml_reader_empty_element(VALUE self)
1103
- {
1104
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1105
- return xmlTextReaderIsEmptyElement(xreader) ? Qtrue : Qfalse;
1106
- }
1107
-
1108
- /*
1109
- * call-seq:
1110
- * reader.valid? -> bool
1111
- *
1112
- * Retrieve the validity status from the parser context.
1113
- */
1114
- static VALUE rxml_reader_valid(VALUE self)
1115
- {
1116
- xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1117
- return xmlTextReaderIsValid(xreader) ? Qtrue : Qfalse;
1118
- }
1119
-
1120
- void rxml_init_reader(void)
1121
- {
1122
- BASE_URI_SYMBOL = ID2SYM(rb_intern("base_uri"));
1123
- ENCODING_SYMBOL = ID2SYM(rb_intern("encoding"));
1124
- IO_ATTR = rb_intern("@io");
1125
- OPTIONS_SYMBOL = ID2SYM(rb_intern("options"));
1126
-
1127
- cXMLReader = rb_define_class_under(mXML, "Reader", rb_cObject);
1128
-
1129
- rb_define_singleton_method(cXMLReader, "document", rxml_reader_document, 1);
1130
- rb_define_singleton_method(cXMLReader, "file", rxml_reader_file, -1);
1131
- rb_define_singleton_method(cXMLReader, "io", rxml_reader_io, -1);
1132
- rb_define_singleton_method(cXMLReader, "string", rxml_reader_string, -1);
1133
-
1134
- rb_define_method(cXMLReader, "[]", rxml_reader_attribute, 1);
1135
- rb_define_method(cXMLReader, "attribute_count", rxml_reader_attr_count, 0);
1136
- rb_define_method(cXMLReader, "base_uri", rxml_reader_base_uri, 0);
1137
- #if LIBXML_VERSION >= 20618
1138
- rb_define_method(cXMLReader, "byte_consumed", rxml_reader_byte_consumed, 0);
1139
- #endif
1140
- rb_define_method(cXMLReader, "close", rxml_reader_close, 0);
1141
- #if LIBXML_VERSION >= 20617
1142
- rb_define_method(cXMLReader, "column_number", rxml_reader_column_number, 0);
1143
- #endif
1144
- rb_define_method(cXMLReader, "depth", rxml_reader_depth, 0);
1145
- rb_define_method(cXMLReader, "encoding", rxml_reader_encoding, 0);
1146
- rb_define_method(cXMLReader, "expand", rxml_reader_expand, 0);
1147
- rb_define_method(cXMLReader, "get_attribute", rxml_reader_get_attribute, 1);
1148
- rb_define_method(cXMLReader, "get_attribute_no", rxml_reader_get_attribute_no, 1);
1149
- rb_define_method(cXMLReader, "get_attribute_ns", rxml_reader_get_attribute_ns, 2);
1150
- rb_define_method(cXMLReader, "has_attributes?", rxml_reader_has_attributes, 0);
1151
- rb_define_method(cXMLReader, "has_value?", rxml_reader_has_value, 0);
1152
- #if LIBXML_VERSION >= 20617
1153
- rb_define_method(cXMLReader, "line_number", rxml_reader_line_number, 0);
1154
- #endif
1155
- rb_define_method(cXMLReader, "local_name", rxml_reader_local_name, 0);
1156
- rb_define_method(cXMLReader, "lookup_namespace", rxml_reader_lookup_namespace, 1);
1157
- rb_define_method(cXMLReader, "move_to_attribute", rxml_reader_move_to_attr, 1);
1158
- rb_define_method(cXMLReader, "move_to_attribute_no", rxml_reader_move_to_attr_no, 1);
1159
- rb_define_method(cXMLReader, "move_to_attribute_ns", rxml_reader_move_to_attr_ns, 2);
1160
- rb_define_method(cXMLReader, "move_to_first_attribute", rxml_reader_move_to_first_attr, 0);
1161
- rb_define_method(cXMLReader, "move_to_next_attribute", rxml_reader_move_to_next_attr, 0);
1162
- rb_define_method(cXMLReader, "move_to_element", rxml_reader_move_to_element, 0);
1163
- rb_define_method(cXMLReader, "name", rxml_reader_name, 0);
1164
- rb_define_method(cXMLReader, "namespace_uri", rxml_reader_namespace_uri, 0);
1165
- rb_define_method(cXMLReader, "next", rxml_reader_next, 0);
1166
- rb_define_method(cXMLReader, "next_sibling", rxml_reader_next_sibling, 0);
1167
- rb_define_method(cXMLReader, "node", rxml_reader_node, 0);
1168
- rb_define_method(cXMLReader, "node_type", rxml_reader_node_type, 0);
1169
- rb_define_method(cXMLReader, "normalization", rxml_reader_normalization, 0);
1170
- rb_define_method(cXMLReader, "prefix", rxml_reader_prefix, 0);
1171
- rb_define_method(cXMLReader, "quote_char", rxml_reader_quote_char, 0);
1172
- rb_define_method(cXMLReader, "read", rxml_reader_read, 0);
1173
- rb_define_method(cXMLReader, "read_attribute_value", rxml_reader_read_attr_value, 0);
1174
- rb_define_method(cXMLReader, "read_inner_xml", rxml_reader_read_inner_xml, 0);
1175
- rb_define_method(cXMLReader, "read_outer_xml", rxml_reader_read_outer_xml, 0);
1176
- rb_define_method(cXMLReader, "read_state", rxml_reader_read_state, 0);
1177
- rb_define_method(cXMLReader, "read_string", rxml_reader_read_string, 0);
1178
- rb_define_method(cXMLReader, "relax_ng_validate", rxml_reader_relax_ng_validate, 1);
1179
- rb_define_method(cXMLReader, "standalone", rxml_reader_standalone, 0);
1180
- #if LIBXML_VERSION >= 20620
1181
- rb_define_method(cXMLReader, "schema_validate", rxml_reader_schema_validate, 1);
1182
- #endif
1183
- rb_define_method(cXMLReader, "value", rxml_reader_value, 0);
1184
- rb_define_method(cXMLReader, "xml_lang", rxml_reader_xml_lang, 0);
1185
- rb_define_method(cXMLReader, "xml_version", rxml_reader_xml_version, 0);
1186
- rb_define_method(cXMLReader, "default?", rxml_reader_default, 0);
1187
- rb_define_method(cXMLReader, "empty_element?", rxml_reader_empty_element, 0);
1188
- rb_define_method(cXMLReader, "namespace_declaration?", rxml_reader_namespace_declaration, 0);
1189
- rb_define_method(cXMLReader, "valid?", rxml_reader_valid, 0);
1190
-
1191
- /* Constants */
1192
- rb_define_const(cXMLReader, "LOADDTD", INT2FIX(XML_PARSER_LOADDTD));
1193
- rb_define_const(cXMLReader, "DEFAULTATTRS", INT2FIX(XML_PARSER_DEFAULTATTRS));
1194
- rb_define_const(cXMLReader, "VALIDATE", INT2FIX(XML_PARSER_VALIDATE));
1195
- rb_define_const(cXMLReader, "SUBST_ENTITIES", INT2FIX(XML_PARSER_SUBST_ENTITIES));
1196
-
1197
- rb_define_const(cXMLReader, "SEVERITY_VALIDITY_WARNING", INT2FIX(XML_PARSER_SEVERITY_VALIDITY_WARNING));
1198
- rb_define_const(cXMLReader, "SEVERITY_VALIDITY_ERROR", INT2FIX(XML_PARSER_SEVERITY_VALIDITY_ERROR));
1199
- rb_define_const(cXMLReader, "SEVERITY_WARNING", INT2FIX(XML_PARSER_SEVERITY_WARNING));
1200
- rb_define_const(cXMLReader, "SEVERITY_ERROR", INT2FIX(XML_PARSER_SEVERITY_ERROR));
1201
-
1202
- rb_define_const(cXMLReader, "TYPE_NONE", INT2FIX(XML_READER_TYPE_NONE));
1203
- rb_define_const(cXMLReader, "TYPE_ELEMENT", INT2FIX(XML_READER_TYPE_ELEMENT));
1204
- rb_define_const(cXMLReader, "TYPE_ATTRIBUTE", INT2FIX(XML_READER_TYPE_ATTRIBUTE));
1205
- rb_define_const(cXMLReader, "TYPE_TEXT", INT2FIX(XML_READER_TYPE_TEXT));
1206
- rb_define_const(cXMLReader, "TYPE_CDATA", INT2FIX(XML_READER_TYPE_CDATA));
1207
- rb_define_const(cXMLReader, "TYPE_ENTITY_REFERENCE", INT2FIX(XML_READER_TYPE_ENTITY_REFERENCE));
1208
- rb_define_const(cXMLReader, "TYPE_ENTITY", INT2FIX(XML_READER_TYPE_ENTITY));
1209
- rb_define_const(cXMLReader, "TYPE_PROCESSING_INSTRUCTION", INT2FIX(XML_READER_TYPE_PROCESSING_INSTRUCTION));
1210
- rb_define_const(cXMLReader, "TYPE_COMMENT", INT2FIX(XML_READER_TYPE_COMMENT));
1211
- rb_define_const(cXMLReader, "TYPE_DOCUMENT", INT2FIX(XML_READER_TYPE_DOCUMENT));
1212
- rb_define_const(cXMLReader, "TYPE_DOCUMENT_TYPE", INT2FIX(XML_READER_TYPE_DOCUMENT_TYPE));
1213
- rb_define_const(cXMLReader, "TYPE_DOCUMENT_FRAGMENT", INT2FIX(XML_READER_TYPE_DOCUMENT_FRAGMENT));
1214
- rb_define_const(cXMLReader, "TYPE_NOTATION", INT2FIX(XML_READER_TYPE_NOTATION));
1215
- rb_define_const(cXMLReader, "TYPE_WHITESPACE", INT2FIX(XML_READER_TYPE_WHITESPACE));
1216
- rb_define_const(cXMLReader, "TYPE_SIGNIFICANT_WHITESPACE", INT2FIX(XML_READER_TYPE_SIGNIFICANT_WHITESPACE));
1217
- rb_define_const(cXMLReader, "TYPE_END_ELEMENT", INT2FIX(XML_READER_TYPE_END_ELEMENT));
1218
- rb_define_const(cXMLReader, "TYPE_END_ENTITY", INT2FIX(XML_READER_TYPE_END_ENTITY));
1219
- rb_define_const(cXMLReader, "TYPE_XML_DECLARATION", INT2FIX(XML_READER_TYPE_XML_DECLARATION));
1220
-
1221
- /* Read states */
1222
- rb_define_const(cXMLReader, "MODE_INITIAL", INT2FIX(XML_TEXTREADER_MODE_INITIAL));
1223
- rb_define_const(cXMLReader, "MODE_INTERACTIVE", INT2FIX(XML_TEXTREADER_MODE_INTERACTIVE));
1224
- rb_define_const(cXMLReader, "MODE_ERROR", INT2FIX(XML_TEXTREADER_MODE_ERROR));
1225
- rb_define_const(cXMLReader, "MODE_EOF", INT2FIX(XML_TEXTREADER_MODE_EOF));
1226
- rb_define_const(cXMLReader, "MODE_CLOSED", INT2FIX(XML_TEXTREADER_MODE_CLOSED));
1227
- rb_define_const(cXMLReader, "MODE_READING", INT2FIX(XML_TEXTREADER_MODE_READING));
1228
- }
1
+ /* Copyright (c) 2006-2007 Apple Inc.
2
+ * Please see the LICENSE file for copyright and distribution information. */
3
+
4
+ #include "ruby_libxml.h"
5
+ #include "ruby_xml_reader.h"
6
+
7
+ /*
8
+ * Document-class: LibXML::XML::Reader
9
+ *
10
+ * The XML::Reader class provides a simpler, alternative way of parsing an XML
11
+ * document in contrast to XML::Parser or XML::SaxParser. A XML::Reader instance
12
+ * acts like a cursor going forward in a document stream, stopping at each node
13
+ * it encounters. To advance to the next node, simply cadd XML::Reader#read.
14
+ *
15
+ * The XML::Reader API closely matches the DOM Core specification and supports
16
+ * namespaces, xml:base, entity handling and DTDs.
17
+ *
18
+ * To summarize, XML::Reader provides a far simpler API to use versus XML::SaxParser
19
+ * and is more memory efficient than using XML::Parser to create a DOM tree.
20
+ *
21
+ * Example:
22
+ *
23
+ * reader = XML::Reader.string("<foo><bar>1</bar><bar>2</bar><bar>3</bar></foo>")
24
+ * reader.read
25
+ * assert_equal('foo', reader.name)
26
+ * assert_equal(nil, reader.value)
27
+ *
28
+ * 3.times do |i|
29
+ * reader.read
30
+ * assert_equal(XML::Reader::TYPE_ELEMENT, reader.node_type)
31
+ * assert_equal('bar', reader.name)
32
+ * reader.read
33
+ * assert_equal(XML::Reader::TYPE_TEXT, reader.node_type)
34
+ * assert_equal((i + 1).to_s, reader.value)
35
+ * reader.read
36
+ * assert_equal(XML::Reader::TYPE_END_ELEMENT, reader.node_type)
37
+ * end
38
+ *
39
+ * You can also parse documents (see XML::Reader.document),
40
+ * strings (see XML::Parser.string) and io objects (see
41
+ * XML::Parser.io).
42
+ *
43
+ * For a more in depth tutorial, albeit in C, see http://xmlsoft.org/xmlreader.html.*/
44
+
45
+
46
+ /* NOTE - We need to wrap the readers document to support Reader.read.node.find('/').
47
+ To do this we need to use xmlTextReaderCurrentDoc which means we have to free the
48
+ document ourselves. Annoying... */
49
+
50
+ VALUE cXMLReader;
51
+
52
+ static ID BASE_URI_SYMBOL;
53
+ static ID ENCODING_SYMBOL;
54
+ static ID IO_ATTR;
55
+ static ID OPTIONS_SYMBOL;
56
+
57
+ static void rxml_reader_free(xmlTextReaderPtr xreader)
58
+ {
59
+ xmlFreeTextReader(xreader);
60
+ }
61
+
62
+ static void rxml_reader_mark(xmlTextReaderPtr xreader)
63
+ {
64
+ xmlDocPtr xdoc = xmlTextReaderCurrentDoc(xreader);
65
+ VALUE value = rxml_lookup_doc(xdoc);
66
+ rb_gc_mark(value);
67
+ }
68
+
69
+ static VALUE rxml_reader_wrap(xmlTextReaderPtr xreader)
70
+ {
71
+ return Data_Wrap_Struct(cXMLReader, NULL, rxml_reader_free, xreader);
72
+ }
73
+
74
+
75
+ static xmlTextReaderPtr rxml_text_reader_get(VALUE obj)
76
+ {
77
+ xmlTextReaderPtr xreader;
78
+ Data_Get_Struct(obj, xmlTextReader, xreader);
79
+ return xreader;
80
+ }
81
+
82
+ /*
83
+ * call-seq:
84
+ * XML::Reader.document(doc) -> XML::Reader
85
+ *
86
+ * Create an new reader for the specified document.
87
+ */
88
+ VALUE rxml_reader_document(VALUE klass, VALUE doc)
89
+ {
90
+ xmlDocPtr xdoc;
91
+ xmlTextReaderPtr xreader;
92
+
93
+ Data_Get_Struct(doc, xmlDoc, xdoc);
94
+
95
+ xreader = xmlReaderWalker(xdoc);
96
+
97
+ if (xreader == NULL)
98
+ rxml_raise(&xmlLastError);
99
+
100
+ return rxml_reader_wrap(xreader);
101
+ }
102
+
103
+ /* call-seq:
104
+ * XML::Reader.file(path) -> XML::Reader
105
+ * XML::Reader.file(path, :encoding => XML::Encoding::UTF_8,
106
+ * :options => XML::Parser::Options::NOENT) -> XML::Parser
107
+ *
108
+ * Creates a new reader by parsing the specified file or uri.
109
+ *
110
+ * You may provide an optional hash table to control how the
111
+ * parsing is performed. Valid options are:
112
+ *
113
+ * encoding - The document encoding, defaults to nil. Valid values
114
+ * are the encoding constants defined on XML::Encoding.
115
+ * options - Controls the execution of the parser, defaults to 0.
116
+ * Valid values are the constants defined on
117
+ * XML::Parser::Options. Mutliple options can be combined
118
+ * by using Bitwise OR (|).
119
+ */
120
+ static VALUE rxml_reader_file(int argc, VALUE *argv, VALUE klass)
121
+ {
122
+ xmlTextReaderPtr xreader;
123
+ VALUE path;
124
+ VALUE options;
125
+
126
+ const char *xencoding = NULL;
127
+ int xoptions = 0;
128
+
129
+ rb_scan_args(argc, argv, "11", &path, &options);
130
+ Check_Type(path, T_STRING);
131
+
132
+ if (!NIL_P(options))
133
+ {
134
+ VALUE encoding = Qnil;
135
+ VALUE parserOptions = Qnil;
136
+
137
+ Check_Type(options, T_HASH);
138
+
139
+ encoding = rb_hash_aref(options, BASE_URI_SYMBOL);
140
+ xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
141
+
142
+ parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
143
+ xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
144
+ }
145
+
146
+ xreader = xmlReaderForFile(StringValueCStr(path), xencoding, xoptions);
147
+
148
+ if (xreader == NULL)
149
+ rxml_raise(&xmlLastError);
150
+
151
+ return rxml_reader_wrap(xreader);
152
+ }
153
+
154
+ /* call-seq:
155
+ * XML::Reader.io(io) -> XML::Reader
156
+ * XML::Reader.io(io, :encoding => XML::Encoding::UTF_8,
157
+ * :options => XML::Parser::Options::NOENT) -> XML::Parser
158
+ *
159
+ * Creates a new reader by parsing the specified io object.
160
+ *
161
+ * You may provide an optional hash table to control how the
162
+ * parsing is performed. Valid options are:
163
+ *
164
+ * base_uri - The base url for the parsed document.
165
+ * encoding - The document encoding, defaults to nil. Valid values
166
+ * are the encoding constants defined on XML::Encoding.
167
+ * options - Controls the execution of the parser, defaults to 0.
168
+ * Valid values are the constants defined on
169
+ * XML::Parser::Options. Mutliple options can be combined
170
+ * by using Bitwise OR (|).
171
+ */
172
+ static VALUE rxml_reader_io(int argc, VALUE *argv, VALUE klass)
173
+ {
174
+ xmlTextReaderPtr xreader;
175
+ VALUE result;
176
+ VALUE io;
177
+ VALUE options;
178
+ char *xbaseurl = NULL;
179
+ const char *xencoding = NULL;
180
+ int xoptions = 0;
181
+
182
+ rb_scan_args(argc, argv, "11", &io, &options);
183
+
184
+ if (!NIL_P(options))
185
+ {
186
+ VALUE baseurl = Qnil;
187
+ VALUE encoding = Qnil;
188
+ VALUE parserOptions = Qnil;
189
+
190
+ Check_Type(options, T_HASH);
191
+
192
+ baseurl = rb_hash_aref(options, BASE_URI_SYMBOL);
193
+ xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl);
194
+
195
+ encoding = rb_hash_aref(options, ENCODING_SYMBOL);
196
+ xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
197
+
198
+ parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
199
+ xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
200
+ }
201
+
202
+ xreader = xmlReaderForIO((xmlInputReadCallback) rxml_read_callback, NULL,
203
+ (void *) io,
204
+ xbaseurl, xencoding, xoptions);
205
+
206
+ if (xreader == NULL)
207
+ rxml_raise(&xmlLastError);
208
+
209
+ result = rxml_reader_wrap(xreader);
210
+
211
+ /* Attach io object to parser so it won't get freed.*/
212
+ rb_ivar_set(result, IO_ATTR, io);
213
+
214
+ return result;
215
+ }
216
+
217
+ /* call-seq:
218
+ * XML::Reader.string(io) -> XML::Reader
219
+ * XML::Reader.string(io, :encoding => XML::Encoding::UTF_8,
220
+ * :options => XML::Parser::Options::NOENT) -> XML::Parser
221
+ *
222
+ * Creates a new reader by parsing the specified string.
223
+ *
224
+ * You may provide an optional hash table to control how the
225
+ * parsing is performed. Valid options are:
226
+ *
227
+ * base_uri - The base url for the parsed document.
228
+ * encoding - The document encoding, defaults to nil. Valid values
229
+ * are the encoding constants defined on XML::Encoding.
230
+ * options - Controls the execution of the parser, defaults to 0.
231
+ * Valid values are the constants defined on
232
+ * XML::Parser::Options. Mutliple options can be combined
233
+ * by using Bitwise OR (|).
234
+ */
235
+ static VALUE rxml_reader_string(int argc, VALUE *argv, VALUE klass)
236
+ {
237
+ xmlTextReaderPtr xreader;
238
+ VALUE string;
239
+ VALUE options;
240
+ char *xbaseurl = NULL;
241
+ const char *xencoding = NULL;
242
+ int xoptions = 0;
243
+
244
+ rb_scan_args(argc, argv, "11", &string, &options);
245
+ Check_Type(string, T_STRING);
246
+
247
+ if (!NIL_P(options))
248
+ {
249
+ VALUE baseurl = Qnil;
250
+ VALUE encoding = Qnil;
251
+ VALUE parserOptions = Qnil;
252
+
253
+ Check_Type(options, T_HASH);
254
+
255
+ baseurl = rb_hash_aref(options, BASE_URI_SYMBOL);
256
+ xbaseurl = NIL_P(baseurl) ? NULL : StringValueCStr(baseurl);
257
+
258
+ encoding = rb_hash_aref(options, ENCODING_SYMBOL);
259
+ xencoding = NIL_P(encoding) ? NULL : xmlGetCharEncodingName(NUM2INT(encoding));
260
+
261
+ parserOptions = rb_hash_aref(options, OPTIONS_SYMBOL);
262
+ xoptions = NIL_P(parserOptions) ? 0 : NUM2INT(parserOptions);
263
+ }
264
+
265
+ xreader = xmlReaderForMemory(StringValueCStr(string), (int)RSTRING_LEN(string),
266
+ xbaseurl, xencoding, xoptions);
267
+
268
+ if (xreader == NULL)
269
+ rxml_raise(&xmlLastError);
270
+
271
+ return rxml_reader_wrap(xreader);
272
+ }
273
+
274
+ /*
275
+ * call-seq:
276
+ * reader.close -> code
277
+ *
278
+ * This method releases any resources allocated by the current instance
279
+ * changes the state to Closed and close any underlying input.
280
+ */
281
+ static VALUE rxml_reader_close(VALUE self)
282
+ {
283
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
284
+ return INT2FIX(xmlTextReaderClose(xreader));
285
+ }
286
+
287
+ /*
288
+ * call-seq:
289
+ * reader.move_to_attribute_no(index) -> code
290
+ *
291
+ * Move the position of the current instance to the attribute with the
292
+ * specified index relative to the containing element.
293
+ */
294
+ static VALUE rxml_reader_move_to_attr_no(VALUE self, VALUE index)
295
+ {
296
+ int ret;
297
+ xmlTextReaderPtr xreader;
298
+
299
+ xreader = rxml_text_reader_get(self);
300
+ ret = xmlTextReaderMoveToAttributeNo(xreader, FIX2INT(index));
301
+
302
+ return INT2FIX(ret);
303
+ }
304
+
305
+ /*
306
+ * call-seq:
307
+ * reader.move_to_attribute(localName) -> code
308
+ *
309
+ * Move the position of the current instance to the attribute with the
310
+ * specified name relative to the containing element.
311
+ */
312
+ static VALUE rxml_reader_move_to_attr(VALUE self, VALUE val)
313
+ {
314
+ if (TYPE(val) == T_FIXNUM)
315
+ {
316
+ rb_warn("%s::move_to_attribute with a Fixnum argument is deprecated. "
317
+ "Please, consider move_to_attribute_no method instead.",
318
+ rb_class2name(cXMLReader));
319
+ return rxml_reader_move_to_attr_no(self, val);
320
+ }
321
+ else
322
+ {
323
+ int ret;
324
+ xmlTextReaderPtr xreader;
325
+
326
+ xreader = rxml_text_reader_get(self);
327
+ ret = xmlTextReaderMoveToAttribute(xreader,
328
+ (const xmlChar *) StringValueCStr(val));
329
+
330
+ return INT2FIX(ret);
331
+ }
332
+ }
333
+
334
+ /*
335
+ * call-seq:
336
+ * reader.move_to_attribute_ns(localName, namespaceURI) -> code
337
+ *
338
+ * Move the position of the current instance to the attribute with the
339
+ * specified name and namespace relative to the containing element.
340
+ */
341
+ static VALUE rxml_reader_move_to_attr_ns(VALUE self, VALUE name, VALUE ns)
342
+ {
343
+ int ret;
344
+ xmlTextReaderPtr xreader;
345
+
346
+ xreader = rxml_text_reader_get(self);
347
+ ret = xmlTextReaderMoveToAttributeNs(xreader,
348
+ (const xmlChar *) StringValueCStr(name),
349
+ (const xmlChar *) StringValueCStr(ns));
350
+
351
+ return INT2FIX(ret);
352
+ }
353
+
354
+ /*
355
+ * call-seq:
356
+ * reader.move_to_first_attribute -> code
357
+ *
358
+ * Move the position of the current instance to the first attribute associated
359
+ * with the current node.
360
+ */
361
+ static VALUE rxml_reader_move_to_first_attr(VALUE self)
362
+ {
363
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
364
+ return INT2FIX(xmlTextReaderMoveToFirstAttribute(xreader));
365
+ }
366
+
367
+ /*
368
+ * call-seq:
369
+ * reader.move_to_next_attribute -> code
370
+ *
371
+ * Move the position of the current instance to the next attribute associated
372
+ * with the current node.
373
+ */
374
+ static VALUE rxml_reader_move_to_next_attr(VALUE self)
375
+ {
376
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
377
+ return INT2FIX(xmlTextReaderMoveToNextAttribute(xreader));
378
+ }
379
+
380
+ /*
381
+ * call-seq:
382
+ * reader.move_to_element -> code
383
+ *
384
+ * Move the position of the current instance to the node that contains the
385
+ * current attribute node.
386
+ */
387
+ static VALUE rxml_reader_move_to_element(VALUE self)
388
+ {
389
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
390
+ return INT2FIX(xmlTextReaderMoveToElement(xreader));
391
+ }
392
+
393
+ /*
394
+ * call-seq:
395
+ * reader.next -> code
396
+ *
397
+ * Skip to the node following the current one in document order while avoiding
398
+ * the subtree if any.
399
+ */
400
+ static VALUE rxml_reader_next(VALUE self)
401
+ {
402
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
403
+ return INT2FIX(xmlTextReaderNext(xreader));
404
+ }
405
+
406
+ /*
407
+ * call-seq:
408
+ * reader.next_sibling -> code
409
+ *
410
+ * Skip to the node following the current one in document order while avoiding
411
+ * the subtree if any. Currently implemented only for Readers built on a
412
+ * document.
413
+ */
414
+ static VALUE rxml_reader_next_sibling(VALUE self)
415
+ {
416
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
417
+ return INT2FIX(xmlTextReaderNextSibling(xreader));
418
+ }
419
+
420
+ /*
421
+ * call-seq:
422
+ * reader.node -> XML::Node
423
+ *
424
+ * Returns the reader's current node. It will return
425
+ * nil if Reader#read has not yet been called.
426
+ * WARNING - Using this method is dangerous because the
427
+ * the node may be destroyed on the next #read.
428
+ */
429
+ static VALUE rxml_reader_node(VALUE self)
430
+ {
431
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
432
+ xmlNodePtr xnode = xmlTextReaderCurrentNode(xreader);
433
+ return xnode ? rxml_node_wrap(xnode) : Qnil;
434
+ }
435
+
436
+ /*
437
+ * call-seq:
438
+ * reader.node_type -> type
439
+ *
440
+ * Get the node type of the current node. Reference:
441
+ * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
442
+ */
443
+ static VALUE rxml_reader_node_type(VALUE self)
444
+ {
445
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
446
+ return INT2FIX(xmlTextReaderNodeType(xreader));
447
+ }
448
+
449
+ /*
450
+ * call-seq:
451
+ * reader.normalization -> value
452
+ *
453
+ * The value indicating whether to normalize white space and attribute values.
454
+ * Since attribute value and end of line normalizations are a MUST in the XML
455
+ * specification only the value true is accepted. The broken bahaviour of
456
+ * accepting out of range character entities like &#0; is of course not
457
+ * supported either.
458
+ *
459
+ * Return 1 or -1 in case of error.
460
+ */
461
+ static VALUE rxml_reader_normalization(VALUE self)
462
+ {
463
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
464
+ return INT2FIX(xmlTextReaderNormalization(xreader));
465
+ }
466
+
467
+ /*
468
+ * call-seq:
469
+ * reader.read -> nil|true|false
470
+ *
471
+ * Causes the reader to move to the next node in the stream, exposing its properties.
472
+ *
473
+ * Returns true if a node was successfully read or false if there are no more
474
+ * nodes to read. On errors, an exception is raised.*/
475
+ static VALUE rxml_reader_read(VALUE self)
476
+ {
477
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
478
+ int result = xmlTextReaderRead(xreader);
479
+ switch(result)
480
+ {
481
+ case -1:
482
+ rxml_raise(&xmlLastError);
483
+ return Qnil;
484
+ break;
485
+ case 0:
486
+ return Qfalse;
487
+ case 1:
488
+ return Qtrue;
489
+ default:
490
+ rb_raise(rb_eRuntimeError,
491
+ "xmlTextReaderRead did not return -1, 0 or 1. Return value was: %d", result);
492
+ }
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * reader.read_attribute_value -> code
498
+ *
499
+ * Parse an attribute value into one or more Text and EntityReference nodes.
500
+ *
501
+ * Return 1 in case of success, 0 if the reader was not positionned on an
502
+ * attribute node or all the attribute values have been read, or -1 in case of
503
+ * error.
504
+ */
505
+ static VALUE rxml_reader_read_attr_value(VALUE self)
506
+ {
507
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
508
+ return INT2FIX(xmlTextReaderReadAttributeValue(xreader));
509
+ }
510
+
511
+ /*
512
+ * call-seq:
513
+ * reader.read_inner_xml -> data
514
+ *
515
+ * Read the contents of the current node, including child nodes and markup.
516
+ *
517
+ * Return a string containing the XML content, or nil if the current node is
518
+ * neither an element nor attribute, or has no child nodes.
519
+ */
520
+ static VALUE rxml_reader_read_inner_xml(VALUE self)
521
+ {
522
+ VALUE result = Qnil;
523
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
524
+
525
+ xmlChar *xml = xmlTextReaderReadInnerXml(xReader);
526
+
527
+ if (xml)
528
+ {
529
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
530
+ result = rxml_new_cstr( xml, xencoding);
531
+ xmlFree(xml);
532
+ }
533
+
534
+ return result;
535
+ }
536
+
537
+ /*
538
+ * call-seq:
539
+ * reader.read_outer_xml -> data
540
+ *
541
+ * Read the contents of the current node, including child nodes and markup.
542
+ *
543
+ * Return a string containing the XML content, or nil if the current node is
544
+ * neither an element nor attribute, or has no child nodes.
545
+ */
546
+ static VALUE rxml_reader_read_outer_xml(VALUE self)
547
+ {
548
+ VALUE result = Qnil;
549
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
550
+
551
+ xmlChar *xml = xmlTextReaderReadOuterXml(xReader);
552
+
553
+ if (xml)
554
+ {
555
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
556
+ result = rxml_new_cstr( xml, xencoding);
557
+ xmlFree(xml);
558
+ }
559
+
560
+ return result;
561
+ }
562
+
563
+ /*
564
+ * call-seq:
565
+ * reader.read_state -> state
566
+ *
567
+ * Get the read state of the reader.
568
+ */
569
+ static VALUE rxml_reader_read_state(VALUE self)
570
+ {
571
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
572
+ return INT2FIX(xmlTextReaderReadState(xreader));
573
+ }
574
+
575
+ /*
576
+ * call-seq:
577
+ * reader.read_string -> string
578
+ *
579
+ * Read the contents of an element or a text node as a string.
580
+ *
581
+ * Return a string containing the contents of the Element or Text node, or nil
582
+ * if the reader is positioned on any other type of node.
583
+ */
584
+ static VALUE rxml_reader_read_string(VALUE self)
585
+ {
586
+ VALUE result = Qnil;
587
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
588
+
589
+ xmlChar *xml = xmlTextReaderReadString(xReader);
590
+
591
+ if (xml)
592
+ {
593
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
594
+ result = rxml_new_cstr( xml, xencoding);
595
+ xmlFree(xml);
596
+ }
597
+
598
+ return result;
599
+ }
600
+
601
+ /*
602
+ * call-seq:
603
+ * reader.relax_ng_validate(rng) -> boolean
604
+ *
605
+ * Use RelaxNG to validate the document as it is processed. Activation is only
606
+ * possible before the first read. If +rng+ is nil, the RelaxNG validation is
607
+ * desactivated.
608
+ *
609
+ * Return true in case the RelaxNG validation could be (des)activated and false in
610
+ * case of error.
611
+ */
612
+ static VALUE rxml_reader_relax_ng_validate(VALUE self, VALUE rng)
613
+ {
614
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
615
+ xmlRelaxNGPtr xrelax;
616
+ int status;
617
+ Data_Get_Struct(rng, xmlRelaxNG, xrelax);
618
+
619
+ status = xmlTextReaderRelaxNGSetSchema(xreader, xrelax);
620
+ return (status == 0 ? Qtrue : Qfalse);
621
+ }
622
+
623
+ #if LIBXML_VERSION >= 20620
624
+ /*
625
+ * call-seq:
626
+ * reader.schema_validate(schema) -> boolean
627
+ *
628
+ * Use W3C XSD schema to validate the document as it is processed. Activation
629
+ * is only possible before the first read. If +schema+ is nil, then XML Schema
630
+ * validation is deactivated.
631
+ *
632
+ * Return false if if the schema's validation could be (de)activated and true
633
+ * otherwise.
634
+ */
635
+ static VALUE
636
+ rxml_reader_schema_validate(VALUE self, VALUE xsd)
637
+ {
638
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
639
+ xmlSchemaPtr xschema;
640
+ int status;
641
+
642
+ Data_Get_Struct(xsd, xmlSchema, xschema);
643
+ status = xmlTextReaderSetSchema(xreader, xschema);
644
+ return (status == 0 ? Qtrue : Qfalse);
645
+ }
646
+ #endif
647
+
648
+ /*
649
+ * call-seq:
650
+ * reader.name -> name
651
+ *
652
+ * Return the qualified name of the node.
653
+ */
654
+ static VALUE rxml_reader_name(VALUE self)
655
+ {
656
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
657
+ const xmlChar *result = xmlTextReaderConstName(xReader);
658
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
659
+
660
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
661
+ }
662
+
663
+ /*
664
+ * call-seq:
665
+ * reader.local_name -> name
666
+ *
667
+ * Return the local name of the node.
668
+ */
669
+ static VALUE rxml_reader_local_name(VALUE self)
670
+ {
671
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
672
+ const xmlChar *result = xmlTextReaderConstLocalName(xReader);
673
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
674
+
675
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
676
+ }
677
+
678
+ /*
679
+ * call-seq:
680
+ * reader.attribute_count -> count
681
+ *
682
+ * Provide the number of attributes of the current node.
683
+ */
684
+ static VALUE rxml_reader_attr_count(VALUE self)
685
+ {
686
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
687
+ return INT2FIX(xmlTextReaderAttributeCount(xreader));
688
+ }
689
+
690
+ /*
691
+ * call-seq:
692
+ * reader.encoding -> XML::Encoding::UTF_8
693
+ *
694
+ * Returns the encoding of the document being read. Note you
695
+ * first have to read data from the reader for encoding
696
+ * to return a value
697
+ *
698
+ * reader = XML::Reader.file(XML_FILE)
699
+ * assert_nil(reader.encoding)
700
+ * reader.read
701
+ * assert_equal(XML::Encoding::UTF_8, reader.encoding)
702
+ *
703
+ * In addition, libxml always appears to return nil for the encoding
704
+ * when parsing strings.
705
+ */
706
+ static VALUE rxml_reader_encoding(VALUE self)
707
+ {
708
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
709
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xreader);
710
+ if (xencoding)
711
+ return INT2NUM(xmlParseCharEncoding((const char*)xencoding));
712
+ else
713
+ return INT2NUM(XML_CHAR_ENCODING_NONE);
714
+ }
715
+
716
+ /*
717
+ * call-seq:
718
+ * reader.base_uri -> URI
719
+ *
720
+ * Determine the base URI of the node.
721
+ */
722
+ static VALUE rxml_reader_base_uri(VALUE self)
723
+ {
724
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
725
+ const xmlChar *result = xmlTextReaderConstBaseUri(xReader);
726
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
727
+
728
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
729
+ }
730
+
731
+ /*
732
+ * call-seq:
733
+ * reader.namespace_uri -> URI
734
+ *
735
+ * Determine the namespace URI of the node.
736
+ */
737
+ static VALUE rxml_reader_namespace_uri(VALUE self)
738
+ {
739
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
740
+ const xmlChar *result = xmlTextReaderConstNamespaceUri(xReader);
741
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
742
+
743
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
744
+ }
745
+
746
+ /*
747
+ * call-seq:
748
+ * reader.value -> text
749
+ *
750
+ * Provide the text value of the node if present.
751
+ */
752
+ static VALUE rxml_reader_value(VALUE self)
753
+ {
754
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
755
+ const xmlChar *result = xmlTextReaderConstValue(xReader);
756
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
757
+
758
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
759
+ }
760
+
761
+ /*
762
+ * call-seq:
763
+ * reader.prefix -> prefix
764
+ *
765
+ * Get a shorthand reference to the namespace associated with the node.
766
+ */
767
+ static VALUE rxml_reader_prefix(VALUE self)
768
+ {
769
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
770
+ const xmlChar *result = xmlTextReaderConstPrefix(xReader);
771
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
772
+
773
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
774
+ }
775
+
776
+ /*
777
+ * call-seq:
778
+ * reader.depth -> depth
779
+ *
780
+ * Get the depth of the node in the tree.
781
+ */
782
+ static VALUE rxml_reader_depth(VALUE self)
783
+ {
784
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
785
+ return INT2FIX(xmlTextReaderDepth(xreader));
786
+ }
787
+
788
+ /*
789
+ * call-seq:
790
+ * reader.quote_char -> char
791
+ *
792
+ * Get the quotation mark character used to enclose the value of an attribute,
793
+ * as an integer value (and -1 in case of error).
794
+ */
795
+ static VALUE rxml_reader_quote_char(VALUE self)
796
+ {
797
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
798
+ return INT2FIX(xmlTextReaderQuoteChar(xreader));
799
+ }
800
+
801
+ /*
802
+ * call-seq:
803
+ * reader.standalone -> code
804
+ *
805
+ * Determine the standalone status of the document being read.
806
+ *
807
+ * Return 1 if the document was declared to be standalone, 0 if it was
808
+ * declared to be not standalone, or -1 if the document did not specify its
809
+ * standalone status or in case of error.
810
+ */
811
+ static VALUE rxml_reader_standalone(VALUE self)
812
+ {
813
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
814
+ return INT2FIX(xmlTextReaderStandalone(xreader));
815
+ }
816
+
817
+ /*
818
+ * call-seq:
819
+ * reader.xml_lang -> value
820
+ *
821
+ * Get the xml:lang scope within which the node resides.
822
+ */
823
+ static VALUE rxml_reader_xml_lang(VALUE self)
824
+ {
825
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
826
+ const xmlChar *result = xmlTextReaderConstXmlLang(xReader);
827
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
828
+
829
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
830
+ }
831
+
832
+ /*
833
+ * call-seq:
834
+ * reader.xml_version -> version
835
+ *
836
+ * Determine the XML version of the document being read.
837
+ */
838
+ static VALUE rxml_reader_xml_version(VALUE self)
839
+ {
840
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
841
+ const xmlChar *result = xmlTextReaderConstXmlVersion(xReader);
842
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
843
+
844
+ return (result == NULL ? Qnil : rxml_new_cstr(result, xencoding));
845
+ }
846
+
847
+ /*
848
+ * call-seq:
849
+ * reader.has_attributes? -> bool
850
+ *
851
+ * Get whether the node has attributes.
852
+ */
853
+ static VALUE rxml_reader_has_attributes(VALUE self)
854
+ {
855
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
856
+ return xmlTextReaderHasAttributes(xreader) ? Qtrue : Qfalse;
857
+ }
858
+
859
+ /*
860
+ * call-seq:
861
+ * reader.has_value? -> bool
862
+ *
863
+ * Get whether the node can have a text value.
864
+ */
865
+ static VALUE rxml_reader_has_value(VALUE self)
866
+ {
867
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
868
+ return xmlTextReaderHasValue(xreader) ? Qtrue : Qfalse;
869
+ }
870
+
871
+ /*
872
+ * call-seq:
873
+ * reader[key] -> value
874
+ *
875
+ * Provide the value of the attribute with the specified index (if +key+ is an
876
+ * integer) or with the specified name (if +key+ is a string) relative to the
877
+ * containing element, as a string.
878
+ */
879
+ static VALUE rxml_reader_attribute(VALUE self, VALUE key)
880
+ {
881
+ VALUE result = Qnil;
882
+ xmlChar *xattr;
883
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
884
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
885
+
886
+ if (TYPE(key) == T_FIXNUM)
887
+ {
888
+ xattr = xmlTextReaderGetAttributeNo(xReader, FIX2INT(key));
889
+ }
890
+ else
891
+ {
892
+ xattr = xmlTextReaderGetAttribute(xReader, (const xmlChar *) StringValueCStr(key));
893
+ }
894
+
895
+ if (xattr)
896
+ {
897
+ result = rxml_new_cstr(xattr, xencoding);
898
+ xmlFree(xattr);
899
+ }
900
+ return result;
901
+ }
902
+
903
+ /*
904
+ * call-seq:
905
+ * reader.get_attribute(localName) -> value
906
+ *
907
+ * Provide the value of the attribute with the specified name
908
+ * relative to the containing element.
909
+ */
910
+ static VALUE rxml_reader_get_attribute(VALUE self, VALUE name)
911
+ {
912
+ VALUE result = Qnil;
913
+ xmlChar *xattr;
914
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
915
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
916
+
917
+ xattr = xmlTextReaderGetAttribute(xReader, (const xmlChar *) StringValueCStr(name));
918
+ if (xattr)
919
+ {
920
+ result = rxml_new_cstr(xattr, xencoding);
921
+ xmlFree(xattr);
922
+ }
923
+ return result;
924
+ }
925
+
926
+ /*
927
+ * call-seq:
928
+ * reader.get_attribute_no(index) -> value
929
+ *
930
+ * Provide the value of the attribute with the specified index
931
+ * relative to the containing element.
932
+ */
933
+ static VALUE rxml_reader_get_attribute_no(VALUE self, VALUE index)
934
+ {
935
+ VALUE result = Qnil;
936
+ xmlChar *xattr;
937
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
938
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
939
+
940
+ xattr = xmlTextReaderGetAttributeNo(xReader, FIX2INT(index));
941
+ if (xattr)
942
+ {
943
+ result = rxml_new_cstr(xattr, xencoding);
944
+ xmlFree(xattr);
945
+ }
946
+ return result;
947
+ }
948
+
949
+ static VALUE rxml_reader_get_attribute_ns(VALUE self, VALUE name, VALUE ns)
950
+ {
951
+ VALUE result = Qnil;
952
+ xmlChar *xattr;
953
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
954
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
955
+
956
+ xattr = xmlTextReaderGetAttributeNs(xReader,
957
+ (const xmlChar *) StringValueCStr(name),
958
+ (const xmlChar *) StringValueCStr(ns));
959
+ if (xattr)
960
+ {
961
+ result = rxml_new_cstr(xattr, xencoding);
962
+ xmlFree(xattr);
963
+ }
964
+ return result;
965
+ }
966
+
967
+ /*
968
+ * call-seq:
969
+ * reader.lookup_namespace(prefix) -> value
970
+ *
971
+ * Resolve a namespace prefix in the scope of the current element.
972
+ * To return the default namespace, specify nil as +prefix+.
973
+ */
974
+ static VALUE rxml_reader_lookup_namespace(VALUE self, VALUE prefix)
975
+ {
976
+ VALUE result = Qnil;
977
+ xmlTextReaderPtr xReader = rxml_text_reader_get(self);
978
+ const xmlChar *xnamespace = xmlTextReaderLookupNamespace(xReader, (const xmlChar *) StringValueCStr(prefix));
979
+ const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
980
+
981
+ if (xnamespace)
982
+ {
983
+ result = rxml_new_cstr(xnamespace, xencoding);
984
+ xmlFree((void *)xnamespace);
985
+ }
986
+ return result;
987
+ }
988
+
989
+ /*
990
+ * call-seq:
991
+ * reader.expand -> node
992
+ *
993
+ * Returns the current node and its full subtree. Note the returned node
994
+ * is valid ONLY until the next read call.
995
+ */
996
+ static VALUE rxml_reader_expand(VALUE self)
997
+ {
998
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
999
+ xmlNodePtr xnode = NULL;
1000
+
1001
+ /* At this point we need to wrap the reader's document as explained above. */
1002
+ xmlDocPtr xdoc = xmlTextReaderCurrentDoc(xreader);
1003
+
1004
+ if (!xdoc)
1005
+ rb_raise(rb_eRuntimeError, "The reader does not have a document. Did you forget to call read?");
1006
+
1007
+ rxml_document_wrap(xdoc);
1008
+
1009
+ /* And now hook in a mark function */
1010
+ RDATA(self)->dmark = (RUBY_DATA_FUNC)rxml_reader_mark;
1011
+
1012
+ xnode = xmlTextReaderExpand(xreader);
1013
+
1014
+ if (!xnode)
1015
+ {
1016
+ return Qnil;
1017
+ }
1018
+ else
1019
+ {
1020
+ return rxml_node_wrap(xnode);
1021
+ }
1022
+ }
1023
+
1024
+ #if LIBXML_VERSION >= 20618
1025
+ /*
1026
+ * call-seq:
1027
+ * reader.byte_consumed -> value
1028
+ *
1029
+ * This method provides the current index of the parser used by the reader,
1030
+ * relative to the start of the current entity.
1031
+ */
1032
+ static VALUE
1033
+ rxml_reader_byte_consumed(VALUE self)
1034
+ {
1035
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1036
+ return INT2NUM(xmlTextReaderByteConsumed(xreader));
1037
+ }
1038
+ #endif
1039
+
1040
+ #if LIBXML_VERSION >= 20617
1041
+ /*
1042
+ * call-seq:
1043
+ * reader.column_number -> number
1044
+ *
1045
+ * Provide the column number of the current parsing point.
1046
+ */
1047
+ static VALUE
1048
+ rxml_reader_column_number(VALUE self)
1049
+ {
1050
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1051
+ return INT2NUM(xmlTextReaderGetParserColumnNumber(xreader));
1052
+ }
1053
+
1054
+ /*
1055
+ * call-seq:
1056
+ * reader.line_number -> number
1057
+ *
1058
+ * Provide the line number of the current parsing point.
1059
+ */
1060
+ static VALUE
1061
+ rxml_reader_line_number(VALUE self)
1062
+ {
1063
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1064
+ return INT2NUM(xmlTextReaderGetParserLineNumber(xreader));
1065
+ }
1066
+ #endif
1067
+
1068
+ /*
1069
+ * call-seq:
1070
+ * reader.default? -> bool
1071
+ *
1072
+ * Return whether an Attribute node was generated from the default value
1073
+ * defined in the DTD or schema.
1074
+ */
1075
+ static VALUE rxml_reader_default(VALUE self)
1076
+ {
1077
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1078
+ return xmlTextReaderIsDefault(xreader) ? Qtrue : Qfalse;
1079
+ }
1080
+
1081
+ /*
1082
+ * call-seq:
1083
+ * reader.namespace_declaration? -> bool
1084
+ *
1085
+ * Determine whether the current node is a namespace declaration rather than a
1086
+ * regular attribute.
1087
+ */
1088
+ static VALUE rxml_reader_namespace_declaration(VALUE self)
1089
+ {
1090
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1091
+ return xmlTextReaderIsNamespaceDecl(xreader) ? Qtrue : Qfalse;
1092
+ }
1093
+
1094
+ /*
1095
+ * call-seq:
1096
+ * reader.empty_element? -> bool
1097
+ *
1098
+ * Check if the current node is empty.
1099
+ */
1100
+ static VALUE rxml_reader_empty_element(VALUE self)
1101
+ {
1102
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1103
+ return xmlTextReaderIsEmptyElement(xreader) ? Qtrue : Qfalse;
1104
+ }
1105
+
1106
+ /*
1107
+ * call-seq:
1108
+ * reader.valid? -> bool
1109
+ *
1110
+ * Retrieve the validity status from the parser context.
1111
+ */
1112
+ static VALUE rxml_reader_valid(VALUE self)
1113
+ {
1114
+ xmlTextReaderPtr xreader = rxml_text_reader_get(self);
1115
+ return xmlTextReaderIsValid(xreader) ? Qtrue : Qfalse;
1116
+ }
1117
+
1118
+ void rxml_init_reader(void)
1119
+ {
1120
+ BASE_URI_SYMBOL = ID2SYM(rb_intern("base_uri"));
1121
+ ENCODING_SYMBOL = ID2SYM(rb_intern("encoding"));
1122
+ IO_ATTR = rb_intern("@io");
1123
+ OPTIONS_SYMBOL = ID2SYM(rb_intern("options"));
1124
+
1125
+ cXMLReader = rb_define_class_under(mXML, "Reader", rb_cObject);
1126
+
1127
+ rb_define_singleton_method(cXMLReader, "document", rxml_reader_document, 1);
1128
+ rb_define_singleton_method(cXMLReader, "file", rxml_reader_file, -1);
1129
+ rb_define_singleton_method(cXMLReader, "io", rxml_reader_io, -1);
1130
+ rb_define_singleton_method(cXMLReader, "string", rxml_reader_string, -1);
1131
+
1132
+ rb_define_method(cXMLReader, "[]", rxml_reader_attribute, 1);
1133
+ rb_define_method(cXMLReader, "attribute_count", rxml_reader_attr_count, 0);
1134
+ rb_define_method(cXMLReader, "base_uri", rxml_reader_base_uri, 0);
1135
+ #if LIBXML_VERSION >= 20618
1136
+ rb_define_method(cXMLReader, "byte_consumed", rxml_reader_byte_consumed, 0);
1137
+ #endif
1138
+ rb_define_method(cXMLReader, "close", rxml_reader_close, 0);
1139
+ #if LIBXML_VERSION >= 20617
1140
+ rb_define_method(cXMLReader, "column_number", rxml_reader_column_number, 0);
1141
+ #endif
1142
+ rb_define_method(cXMLReader, "depth", rxml_reader_depth, 0);
1143
+ rb_define_method(cXMLReader, "encoding", rxml_reader_encoding, 0);
1144
+ rb_define_method(cXMLReader, "expand", rxml_reader_expand, 0);
1145
+ rb_define_method(cXMLReader, "get_attribute", rxml_reader_get_attribute, 1);
1146
+ rb_define_method(cXMLReader, "get_attribute_no", rxml_reader_get_attribute_no, 1);
1147
+ rb_define_method(cXMLReader, "get_attribute_ns", rxml_reader_get_attribute_ns, 2);
1148
+ rb_define_method(cXMLReader, "has_attributes?", rxml_reader_has_attributes, 0);
1149
+ rb_define_method(cXMLReader, "has_value?", rxml_reader_has_value, 0);
1150
+ #if LIBXML_VERSION >= 20617
1151
+ rb_define_method(cXMLReader, "line_number", rxml_reader_line_number, 0);
1152
+ #endif
1153
+ rb_define_method(cXMLReader, "local_name", rxml_reader_local_name, 0);
1154
+ rb_define_method(cXMLReader, "lookup_namespace", rxml_reader_lookup_namespace, 1);
1155
+ rb_define_method(cXMLReader, "move_to_attribute", rxml_reader_move_to_attr, 1);
1156
+ rb_define_method(cXMLReader, "move_to_attribute_no", rxml_reader_move_to_attr_no, 1);
1157
+ rb_define_method(cXMLReader, "move_to_attribute_ns", rxml_reader_move_to_attr_ns, 2);
1158
+ rb_define_method(cXMLReader, "move_to_first_attribute", rxml_reader_move_to_first_attr, 0);
1159
+ rb_define_method(cXMLReader, "move_to_next_attribute", rxml_reader_move_to_next_attr, 0);
1160
+ rb_define_method(cXMLReader, "move_to_element", rxml_reader_move_to_element, 0);
1161
+ rb_define_method(cXMLReader, "name", rxml_reader_name, 0);
1162
+ rb_define_method(cXMLReader, "namespace_uri", rxml_reader_namespace_uri, 0);
1163
+ rb_define_method(cXMLReader, "next", rxml_reader_next, 0);
1164
+ rb_define_method(cXMLReader, "next_sibling", rxml_reader_next_sibling, 0);
1165
+ rb_define_method(cXMLReader, "node", rxml_reader_node, 0);
1166
+ rb_define_method(cXMLReader, "node_type", rxml_reader_node_type, 0);
1167
+ rb_define_method(cXMLReader, "normalization", rxml_reader_normalization, 0);
1168
+ rb_define_method(cXMLReader, "prefix", rxml_reader_prefix, 0);
1169
+ rb_define_method(cXMLReader, "quote_char", rxml_reader_quote_char, 0);
1170
+ rb_define_method(cXMLReader, "read", rxml_reader_read, 0);
1171
+ rb_define_method(cXMLReader, "read_attribute_value", rxml_reader_read_attr_value, 0);
1172
+ rb_define_method(cXMLReader, "read_inner_xml", rxml_reader_read_inner_xml, 0);
1173
+ rb_define_method(cXMLReader, "read_outer_xml", rxml_reader_read_outer_xml, 0);
1174
+ rb_define_method(cXMLReader, "read_state", rxml_reader_read_state, 0);
1175
+ rb_define_method(cXMLReader, "read_string", rxml_reader_read_string, 0);
1176
+ rb_define_method(cXMLReader, "relax_ng_validate", rxml_reader_relax_ng_validate, 1);
1177
+ rb_define_method(cXMLReader, "standalone", rxml_reader_standalone, 0);
1178
+ #if LIBXML_VERSION >= 20620
1179
+ rb_define_method(cXMLReader, "schema_validate", rxml_reader_schema_validate, 1);
1180
+ #endif
1181
+ rb_define_method(cXMLReader, "value", rxml_reader_value, 0);
1182
+ rb_define_method(cXMLReader, "xml_lang", rxml_reader_xml_lang, 0);
1183
+ rb_define_method(cXMLReader, "xml_version", rxml_reader_xml_version, 0);
1184
+ rb_define_method(cXMLReader, "default?", rxml_reader_default, 0);
1185
+ rb_define_method(cXMLReader, "empty_element?", rxml_reader_empty_element, 0);
1186
+ rb_define_method(cXMLReader, "namespace_declaration?", rxml_reader_namespace_declaration, 0);
1187
+ rb_define_method(cXMLReader, "valid?", rxml_reader_valid, 0);
1188
+
1189
+ /* Constants */
1190
+ rb_define_const(cXMLReader, "LOADDTD", INT2FIX(XML_PARSER_LOADDTD));
1191
+ rb_define_const(cXMLReader, "DEFAULTATTRS", INT2FIX(XML_PARSER_DEFAULTATTRS));
1192
+ rb_define_const(cXMLReader, "VALIDATE", INT2FIX(XML_PARSER_VALIDATE));
1193
+ rb_define_const(cXMLReader, "SUBST_ENTITIES", INT2FIX(XML_PARSER_SUBST_ENTITIES));
1194
+
1195
+ rb_define_const(cXMLReader, "SEVERITY_VALIDITY_WARNING", INT2FIX(XML_PARSER_SEVERITY_VALIDITY_WARNING));
1196
+ rb_define_const(cXMLReader, "SEVERITY_VALIDITY_ERROR", INT2FIX(XML_PARSER_SEVERITY_VALIDITY_ERROR));
1197
+ rb_define_const(cXMLReader, "SEVERITY_WARNING", INT2FIX(XML_PARSER_SEVERITY_WARNING));
1198
+ rb_define_const(cXMLReader, "SEVERITY_ERROR", INT2FIX(XML_PARSER_SEVERITY_ERROR));
1199
+
1200
+ rb_define_const(cXMLReader, "TYPE_NONE", INT2FIX(XML_READER_TYPE_NONE));
1201
+ rb_define_const(cXMLReader, "TYPE_ELEMENT", INT2FIX(XML_READER_TYPE_ELEMENT));
1202
+ rb_define_const(cXMLReader, "TYPE_ATTRIBUTE", INT2FIX(XML_READER_TYPE_ATTRIBUTE));
1203
+ rb_define_const(cXMLReader, "TYPE_TEXT", INT2FIX(XML_READER_TYPE_TEXT));
1204
+ rb_define_const(cXMLReader, "TYPE_CDATA", INT2FIX(XML_READER_TYPE_CDATA));
1205
+ rb_define_const(cXMLReader, "TYPE_ENTITY_REFERENCE", INT2FIX(XML_READER_TYPE_ENTITY_REFERENCE));
1206
+ rb_define_const(cXMLReader, "TYPE_ENTITY", INT2FIX(XML_READER_TYPE_ENTITY));
1207
+ rb_define_const(cXMLReader, "TYPE_PROCESSING_INSTRUCTION", INT2FIX(XML_READER_TYPE_PROCESSING_INSTRUCTION));
1208
+ rb_define_const(cXMLReader, "TYPE_COMMENT", INT2FIX(XML_READER_TYPE_COMMENT));
1209
+ rb_define_const(cXMLReader, "TYPE_DOCUMENT", INT2FIX(XML_READER_TYPE_DOCUMENT));
1210
+ rb_define_const(cXMLReader, "TYPE_DOCUMENT_TYPE", INT2FIX(XML_READER_TYPE_DOCUMENT_TYPE));
1211
+ rb_define_const(cXMLReader, "TYPE_DOCUMENT_FRAGMENT", INT2FIX(XML_READER_TYPE_DOCUMENT_FRAGMENT));
1212
+ rb_define_const(cXMLReader, "TYPE_NOTATION", INT2FIX(XML_READER_TYPE_NOTATION));
1213
+ rb_define_const(cXMLReader, "TYPE_WHITESPACE", INT2FIX(XML_READER_TYPE_WHITESPACE));
1214
+ rb_define_const(cXMLReader, "TYPE_SIGNIFICANT_WHITESPACE", INT2FIX(XML_READER_TYPE_SIGNIFICANT_WHITESPACE));
1215
+ rb_define_const(cXMLReader, "TYPE_END_ELEMENT", INT2FIX(XML_READER_TYPE_END_ELEMENT));
1216
+ rb_define_const(cXMLReader, "TYPE_END_ENTITY", INT2FIX(XML_READER_TYPE_END_ENTITY));
1217
+ rb_define_const(cXMLReader, "TYPE_XML_DECLARATION", INT2FIX(XML_READER_TYPE_XML_DECLARATION));
1218
+
1219
+ /* Read states */
1220
+ rb_define_const(cXMLReader, "MODE_INITIAL", INT2FIX(XML_TEXTREADER_MODE_INITIAL));
1221
+ rb_define_const(cXMLReader, "MODE_INTERACTIVE", INT2FIX(XML_TEXTREADER_MODE_INTERACTIVE));
1222
+ rb_define_const(cXMLReader, "MODE_ERROR", INT2FIX(XML_TEXTREADER_MODE_ERROR));
1223
+ rb_define_const(cXMLReader, "MODE_EOF", INT2FIX(XML_TEXTREADER_MODE_EOF));
1224
+ rb_define_const(cXMLReader, "MODE_CLOSED", INT2FIX(XML_TEXTREADER_MODE_CLOSED));
1225
+ rb_define_const(cXMLReader, "MODE_READING", INT2FIX(XML_TEXTREADER_MODE_READING));
1226
+ }