libxml-ruby 5.0.5 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY → CHANGELOG.md} +875 -923
  3. data/LICENSE +20 -20
  4. data/README.md +67 -0
  5. data/Rakefile +77 -98
  6. data/ext/libxml/extconf.rb +34 -20
  7. data/ext/libxml/libxml.c +67 -79
  8. data/ext/libxml/ruby_libxml.h +1 -1
  9. data/ext/libxml/ruby_xml_attr.c +338 -333
  10. data/ext/libxml/ruby_xml_attr.h +13 -12
  11. data/ext/libxml/ruby_xml_attr_decl.c +19 -12
  12. data/ext/libxml/ruby_xml_attr_decl.h +11 -11
  13. data/ext/libxml/ruby_xml_attributes.c +18 -9
  14. data/ext/libxml/ruby_xml_document.c +111 -98
  15. data/ext/libxml/ruby_xml_document.h +1 -0
  16. data/ext/libxml/ruby_xml_dtd.c +49 -19
  17. data/ext/libxml/ruby_xml_dtd.h +10 -9
  18. data/ext/libxml/ruby_xml_html_parser.c +91 -91
  19. data/ext/libxml/ruby_xml_html_parser.h +10 -10
  20. data/ext/libxml/ruby_xml_html_parser_context.c +19 -6
  21. data/ext/libxml/ruby_xml_html_parser_context.h +11 -10
  22. data/ext/libxml/ruby_xml_html_parser_options.c +48 -48
  23. data/ext/libxml/ruby_xml_html_parser_options.h +10 -10
  24. data/ext/libxml/ruby_xml_input_cbg.c +45 -17
  25. data/ext/libxml/ruby_xml_input_cbg.h +20 -20
  26. data/ext/libxml/ruby_xml_io.c +49 -47
  27. data/ext/libxml/ruby_xml_io.h +10 -10
  28. data/ext/libxml/ruby_xml_namespace.c +20 -12
  29. data/ext/libxml/ruby_xml_namespace.h +11 -10
  30. data/ext/libxml/ruby_xml_namespaces.c +313 -293
  31. data/ext/libxml/ruby_xml_namespaces.h +9 -9
  32. data/ext/libxml/ruby_xml_node.c +71 -32
  33. data/ext/libxml/ruby_xml_node.h +15 -13
  34. data/ext/libxml/ruby_xml_parser.c +91 -91
  35. data/ext/libxml/ruby_xml_parser_context.c +54 -47
  36. data/ext/libxml/ruby_xml_parser_context.h +11 -10
  37. data/ext/libxml/ruby_xml_reader.c +25 -15
  38. data/ext/libxml/ruby_xml_reader.h +14 -14
  39. data/ext/libxml/ruby_xml_registry.c +31 -0
  40. data/ext/libxml/ruby_xml_registry.h +22 -0
  41. data/ext/libxml/ruby_xml_relaxng.c +21 -5
  42. data/ext/libxml/ruby_xml_relaxng.h +9 -8
  43. data/ext/libxml/ruby_xml_sax2_handler.h +10 -10
  44. data/ext/libxml/ruby_xml_sax_parser.c +1 -1
  45. data/ext/libxml/ruby_xml_sax_parser.h +10 -10
  46. data/ext/libxml/ruby_xml_schema.c +18 -11
  47. data/ext/libxml/ruby_xml_schema.h +26 -25
  48. data/ext/libxml/ruby_xml_schema_attribute.c +7 -7
  49. data/ext/libxml/ruby_xml_schema_attribute.h +37 -37
  50. data/ext/libxml/ruby_xml_schema_element.c +8 -8
  51. data/ext/libxml/ruby_xml_schema_element.h +11 -11
  52. data/ext/libxml/ruby_xml_schema_facet.c +50 -50
  53. data/ext/libxml/ruby_xml_schema_facet.h +9 -9
  54. data/ext/libxml/ruby_xml_schema_type.c +12 -19
  55. data/ext/libxml/ruby_xml_schema_type.h +9 -9
  56. data/ext/libxml/ruby_xml_version.h +4 -4
  57. data/ext/libxml/ruby_xml_writer.c +1136 -1124
  58. data/ext/libxml/ruby_xml_writer.h +6 -6
  59. data/ext/libxml/ruby_xml_xinclude.c +20 -20
  60. data/ext/libxml/ruby_xml_xinclude.h +11 -11
  61. data/ext/libxml/ruby_xml_xpath.c +195 -195
  62. data/ext/libxml/ruby_xml_xpath.h +15 -15
  63. data/ext/libxml/ruby_xml_xpath_context.c +408 -362
  64. data/ext/libxml/ruby_xml_xpath_context.h +9 -9
  65. data/ext/libxml/ruby_xml_xpath_expression.c +11 -5
  66. data/ext/libxml/ruby_xml_xpath_expression.h +11 -10
  67. data/ext/libxml/ruby_xml_xpath_object.c +69 -54
  68. data/ext/libxml/ruby_xml_xpath_object.h +19 -17
  69. data/ext/vc/libxml_ruby/libxml_ruby.vcxproj +271 -0
  70. data/ext/xcode/libxml-ruby.xcodeproj/project.pbxproj +633 -0
  71. data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  72. data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  73. data/ext/xcode/libxml-ruby.xcodeproj/xcshareddata/xcschemes/libxml-ruby.xcscheme +80 -0
  74. data/lib/libxml/document.rb +0 -29
  75. data/lib/libxml/error.rb +30 -3
  76. data/lib/libxml/html_parser.rb +0 -16
  77. data/lib/libxml/node.rb +1 -3
  78. data/lib/libxml/parser.rb +0 -8
  79. data/lib/libxml/schema/attribute.rb +27 -19
  80. data/lib/libxml/schema/element.rb +20 -0
  81. data/lib/libxml/schema/type.rb +44 -21
  82. data/lib/libxml/schema.rb +47 -47
  83. data/lib/libxml-ruby.rb +30 -30
  84. data/libxml-ruby.gemspec +12 -16
  85. data/test/c14n/result/1-1-without-comments/example-1 +3 -3
  86. data/test/c14n/result/1-1-without-comments/example-2 +10 -10
  87. data/test/c14n/result/1-1-without-comments/example-3 +13 -13
  88. data/test/c14n/result/1-1-without-comments/example-4 +8 -8
  89. data/test/c14n/result/1-1-without-comments/example-5 +2 -2
  90. data/test/c14n/result/with-comments/example-1 +5 -5
  91. data/test/c14n/result/with-comments/example-2 +10 -10
  92. data/test/c14n/result/with-comments/example-3 +13 -13
  93. data/test/c14n/result/with-comments/example-4 +8 -8
  94. data/test/c14n/result/with-comments/example-5 +3 -3
  95. data/test/c14n/result/without-comments/example-1 +3 -3
  96. data/test/c14n/result/without-comments/example-2 +10 -10
  97. data/test/c14n/result/without-comments/example-3 +13 -13
  98. data/test/c14n/result/without-comments/example-4 +8 -8
  99. data/test/c14n/result/without-comments/example-5 +2 -2
  100. data/test/test_attr.rb +179 -180
  101. data/test/test_attr_decl.rb +131 -131
  102. data/test/test_attributes.rb +135 -135
  103. data/test/test_canonicalize.rb +122 -120
  104. data/test/test_document.rb +2 -4
  105. data/test/test_dtd.rb +12 -4
  106. data/test/test_encoding_sax.rb +114 -114
  107. data/test/test_error.rb +6 -3
  108. data/test/test_helper.rb +1 -0
  109. data/test/test_html_parser.rb +6 -2
  110. data/test/test_html_parser_context.rb +22 -22
  111. data/test/test_input_callbacks.rb +36 -0
  112. data/test/test_namespace.rb +1 -1
  113. data/test/test_namespaces.rb +200 -200
  114. data/test/test_node.rb +16 -0
  115. data/test/test_node_cdata.rb +50 -50
  116. data/test/test_node_comment.rb +32 -32
  117. data/test/test_node_copy.rb +40 -40
  118. data/test/test_node_edit.rb +176 -158
  119. data/test/test_node_pi.rb +37 -37
  120. data/test/test_node_text.rb +69 -69
  121. data/test/test_node_xlink.rb +28 -28
  122. data/test/test_parser.rb +5 -41
  123. data/test/test_parser_context.rb +198 -198
  124. data/test/test_properties.rb +38 -38
  125. data/test/test_reader.rb +55 -6
  126. data/test/test_relaxng.rb +59 -53
  127. data/test/test_sax_parser.rb +345 -345
  128. data/test/test_schema.rb +28 -0
  129. data/test/test_traversal.rb +152 -152
  130. data/test/test_writer.rb +469 -468
  131. data/test/test_xinclude.rb +20 -20
  132. data/test/test_xml.rb +3 -7
  133. data/test/test_xpath.rb +244 -244
  134. data/test/test_xpath_context.rb +87 -87
  135. data/test/test_xpath_expression.rb +37 -37
  136. metadata +33 -27
  137. data/README.rdoc +0 -208
  138. data/ext/libxml/extconf.h +0 -3
  139. data/ext/libxml/ruby_xml_cbg.c +0 -85
  140. data/lib/libxml/hpricot.rb +0 -78
  141. data/lib/libxml.rb +0 -5
  142. data/lib/xml/libxml.rb +0 -10
  143. data/lib/xml.rb +0 -14
  144. data/script/benchmark/depixelate +0 -634
  145. data/script/benchmark/hamlet.xml +0 -9055
  146. data/script/benchmark/parsecount +0 -170
  147. data/script/benchmark/sock_entries.xml +0 -507
  148. data/script/benchmark/throughput +0 -41
  149. data/script/test +0 -6
  150. data/test/test.rb +0 -5
  151. data/test/test_deprecated_require.rb +0 -12
@@ -8,6 +8,10 @@
8
8
 
9
9
  VALUE cXMLNode;
10
10
 
11
+ #ifndef TYPED_DATA_EMBEDDED
12
+ #define TYPED_DATA_EMBEDDED ((VALUE)1)
13
+ #endif
14
+
11
15
  /* Document-class: LibXML::XML::Node
12
16
  *
13
17
  * Nodes are the primary objects that make up an XML document.
@@ -26,9 +30,9 @@ VALUE cXMLNode;
26
30
  * have a parent and do not belong to a document). In these cases,
27
31
  * the bindings manage the memory. They do this by installing a free
28
32
  * function and storing a back pointer to the Ruby object from the xmlnode
29
- * using the _private member on libxml structures. When the Ruby object
30
- * goes out of scope, the underlying libxml structure is freed. Libxml
31
- * itself then frees all child node (recursively).
33
+ * using a pointer-keyed registry (see ruby_xml_registry.c). When the
34
+ * Ruby object goes out of scope, the underlying libxml structure is freed.
35
+ * Libxml itself then frees all child node (recursively).
32
36
  *
33
37
  * For all other nodes (the vast majority), the bindings create temporary
34
38
  * Ruby objects that get freed once they go out of scope. Thus there can be
@@ -46,29 +50,71 @@ VALUE cXMLNode;
46
50
  * and are no longer in scope (since if they were the document would not be freed).
47
51
  */
48
52
 
49
- static void rxml_node_free(xmlNodePtr xnode)
53
+ static void rxml_node_free(void *data)
50
54
  {
55
+ xmlNodePtr xnode = (xmlNodePtr)data;
56
+ if (!xnode) return;
57
+
51
58
  /* The ruby object wrapping the xml object no longer exists and this
52
- is a standalone node without a document or parent so ruby is
59
+ is a standalone node without a document or parent so ruby is
53
60
  responsible for freeing the underlying node.*/
54
61
  if (xnode->doc == NULL && xnode->parent == NULL)
55
62
  {
56
- // Remove the back linkage from libxml to Ruby
57
- xnode->_private = NULL;
63
+ rxml_registry_unregister(xnode);
58
64
  xmlFreeNode(xnode);
59
65
  }
60
66
  }
61
67
 
68
+ /* Three TypedData types are used for nodes, all sharing rxml_node_data_type
69
+ * as the parent type so that TypedData_Get_Struct type checks pass for any
70
+ * variant:
71
+ *
72
+ * rxml_node_data_type - Default. Marks the owning document to prevent
73
+ * GC from collecting it. No free function since
74
+ * libxml owns the node memory.
75
+ *
76
+ * rxml_node_unmanaged_data_type - No mark, no free. Used for transient nodes
77
+ * whose lifetime is not controlled by Ruby (e.g.
78
+ * nodes returned by xmlTextReaderExpand that are
79
+ * freed on the next reader read call).
80
+ *
81
+ * rxml_node_managed_data_type - Marks the document and frees standalone nodes
82
+ * (no doc, no parent) when the Ruby wrapper is
83
+ * collected. Used for nodes created from Ruby
84
+ * that have not yet been inserted into a document.
85
+ */
86
+ const rb_data_type_t rxml_node_data_type = {
87
+ .wrap_struct_name = "LibXML::XML::Node",
88
+ .function = { .dmark = (RUBY_DATA_FUNC)rxml_node_mark, .dfree = NULL },
89
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
90
+ };
91
+
92
+ const rb_data_type_t rxml_node_unmanaged_data_type = {
93
+ .wrap_struct_name = "LibXML::XML::Node (unmanaged)",
94
+ .function = { .dmark = NULL, .dfree = NULL },
95
+ .parent = &rxml_node_data_type,
96
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
97
+ };
98
+
99
+ static const rb_data_type_t rxml_node_managed_data_type = {
100
+ .wrap_struct_name = "LibXML::XML::Node (managed)",
101
+ .function = { .dmark = (RUBY_DATA_FUNC)rxml_node_mark, .dfree = rxml_node_free },
102
+ .parent = &rxml_node_data_type,
103
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
104
+ };
105
+
62
106
  void rxml_node_manage(xmlNodePtr xnode, VALUE node)
63
107
  {
64
- RDATA(node)->dfree = (RUBY_DATA_FUNC)rxml_node_free;
65
- xnode->_private = (void*)node;
108
+ VALUE *type_ptr = (VALUE *)&RTYPEDDATA(node)->type;
109
+ *type_ptr = (*type_ptr & TYPED_DATA_EMBEDDED) | (VALUE)&rxml_node_managed_data_type;
110
+ rxml_registry_register(xnode, node);
66
111
  }
67
112
 
68
113
  void rxml_node_unmanage(xmlNodePtr xnode, VALUE node)
69
114
  {
70
- RDATA(node)->dfree = NULL;
71
- xnode->_private = NULL;
115
+ VALUE *type_ptr = (VALUE *)&RTYPEDDATA(node)->type;
116
+ *type_ptr = (*type_ptr & TYPED_DATA_EMBEDDED) | (VALUE)&rxml_node_data_type;
117
+ rxml_registry_unregister(xnode);
72
118
  }
73
119
 
74
120
  xmlNodePtr rxml_node_root(xmlNodePtr xnode)
@@ -87,20 +133,16 @@ void rxml_node_mark(xmlNodePtr xnode)
87
133
  {
88
134
  if (xnode->doc)
89
135
  {
90
- if (xnode->doc->_private)
91
- {
92
- VALUE doc = (VALUE)xnode->doc->_private;
93
- rb_gc_mark(doc);
94
- }
136
+ VALUE doc = rxml_registry_lookup(xnode->doc);
137
+ if (!NIL_P(doc))
138
+ rb_gc_mark(doc);
95
139
  }
96
140
  else if (xnode->parent)
97
141
  {
98
142
  xmlNodePtr root = rxml_node_root(xnode);
99
- if (root->_private)
100
- {
101
- VALUE node = (VALUE)root->_private;
143
+ VALUE node = rxml_registry_lookup(root);
144
+ if (!NIL_P(node))
102
145
  rb_gc_mark(node);
103
- }
104
146
  }
105
147
  }
106
148
 
@@ -109,13 +151,10 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
109
151
  VALUE result = Qnil;
110
152
 
111
153
  // Is this node already wrapped?
112
- if (xnode->_private)
113
- {
114
- result = (VALUE)xnode->_private;
115
- }
116
- else
154
+ result = rxml_registry_lookup(xnode);
155
+ if (NIL_P(result))
117
156
  {
118
- result = Data_Wrap_Struct(cXMLNode, rxml_node_mark, NULL, xnode);
157
+ result = TypedData_Wrap_Struct(cXMLNode, &rxml_node_data_type, xnode);
119
158
  }
120
159
 
121
160
  if (!xnode->doc && !xnode->parent)
@@ -128,13 +167,13 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
128
167
  static VALUE rxml_node_alloc(VALUE klass)
129
168
  {
130
169
  // This node was created from Ruby so we are responsible for freeing it not libxml
131
- return Data_Wrap_Struct(klass, rxml_node_mark, rxml_node_free, NULL);
170
+ return TypedData_Wrap_Struct(klass, &rxml_node_data_type, NULL);
132
171
  }
133
172
 
134
173
  static xmlNodePtr rxml_get_xnode(VALUE node)
135
174
  {
136
175
  xmlNodePtr result;
137
- Data_Get_Struct(node, xmlNode, result);
176
+ TypedData_Get_Struct(node, xmlNode, &rxml_node_data_type, result);
138
177
 
139
178
  if (!result)
140
179
  rb_raise(rb_eRuntimeError, "This node has already been freed.");
@@ -283,7 +322,7 @@ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
283
322
  name = rb_obj_as_string(name);
284
323
 
285
324
  if (!NIL_P(ns))
286
- Data_Get_Struct(ns, xmlNs, xns);
325
+ TypedData_Get_Struct(ns, xmlNs, &rxml_namespace_type, xns);
287
326
 
288
327
  xnode = xmlNewNode(xns, (xmlChar*) StringValuePtr(name));
289
328
 
@@ -291,7 +330,7 @@ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
291
330
  rxml_raise(xmlGetLastError());
292
331
 
293
332
  // Link the ruby wrapper to the underlying libxml node
294
- RDATA(self)->data = xnode;
333
+ RTYPEDDATA_DATA(self) = xnode;
295
334
 
296
335
  // Ruby is in charge of managing this node's memory
297
336
  rxml_node_manage(xnode, self);
@@ -329,7 +368,7 @@ static VALUE rxml_node_modify_dom(VALUE self, VALUE target,
329
368
 
330
369
  /* Assume the target was freed, we need to fix up the ruby object to point to the
331
370
  newly returned node. */
332
- RDATA(target)->data = xresult;
371
+ RTYPEDDATA_DATA(target) = xresult;
333
372
 
334
373
  return target;
335
374
  }
@@ -533,7 +572,7 @@ static VALUE rxml_node_doc(VALUE self)
533
572
  if (xdoc == NULL)
534
573
  return (Qnil);
535
574
 
536
- return (VALUE)xdoc->_private;
575
+ return rxml_registry_lookup(xdoc);
537
576
  }
538
577
 
539
578
  /*
@@ -1,13 +1,15 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- #ifndef __RXML_NODE__
4
- #define __RXML_NODE__
5
-
6
- extern VALUE cXMLNode;
7
-
8
- void rxml_init_node(void);
9
- void rxml_node_mark(xmlNodePtr xnode);
10
- VALUE rxml_node_wrap(xmlNodePtr xnode);
11
- void rxml_node_manage(xmlNodePtr xnode, VALUE node);
12
- void rxml_node_unmanage(xmlNodePtr xnode, VALUE node);
13
- #endif
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_NODE__
4
+ #define __RXML_NODE__
5
+
6
+ extern VALUE cXMLNode;
7
+ extern const rb_data_type_t rxml_node_data_type;
8
+ extern const rb_data_type_t rxml_node_unmanaged_data_type;
9
+
10
+ void rxml_init_node(void);
11
+ void rxml_node_mark(xmlNodePtr xnode);
12
+ VALUE rxml_node_wrap(xmlNodePtr xnode);
13
+ void rxml_node_manage(xmlNodePtr xnode, VALUE node);
14
+ void rxml_node_unmanage(xmlNodePtr xnode, VALUE node);
15
+ #endif
@@ -1,91 +1,91 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- #include <stdarg.h>
4
- #include "ruby_libxml.h"
5
-
6
- /*
7
- * Document-class: LibXML::XML::Parser
8
- *
9
- * The XML::Parser provides a tree based API for processing
10
- * xml documents, in contract to XML::Reader's stream
11
- * based api and XML::SaxParser callback based API.
12
- *
13
- * As a result, parsing a document creates an in-memory document object
14
- * that consist of any number of XML::Node instances. This is simple
15
- * and powerful model, but has the major limitation that the size of
16
- * the document that can be processed is limited by the amount of
17
- * memory available. In such cases, it is better to use the XML::Reader.
18
- *
19
- * Using the parser is simple:
20
- *
21
- * parser = XML::Parser.file('my_file')
22
- * doc = parser.parse
23
- *
24
- * You can also parse documents (see XML::Parser.document),
25
- * strings (see XML::Parser.string) and io objects (see
26
- * XML::Parser.io).
27
- */
28
-
29
- VALUE cXMLParser;
30
- static ID CONTEXT_ATTR;
31
-
32
- /*
33
- * call-seq:
34
- * parser.initialize(context) -> XML::Parser
35
- *
36
- * Creates a new XML::Parser from the specified
37
- * XML::Parser::Context.
38
- */
39
- static VALUE rxml_parser_initialize(int argc, VALUE *argv, VALUE self)
40
- {
41
- VALUE context = Qnil;
42
-
43
- rb_scan_args(argc, argv, "01", &context);
44
-
45
- if (context == Qnil)
46
- {
47
- rb_raise(rb_eArgError, "An instance of a XML::Parser::Context must be passed to XML::Parser.new");
48
- }
49
-
50
- rb_ivar_set(self, CONTEXT_ATTR, context);
51
- return self;
52
- }
53
-
54
- /*
55
- * call-seq:
56
- * parser.parse -> XML::Document
57
- *
58
- * Parse the input XML and create an XML::Document with
59
- * it's content. If an error occurs, XML::Parser::ParseError
60
- * is thrown.
61
- */
62
- static VALUE rxml_parser_parse(VALUE self)
63
- {
64
- xmlParserCtxtPtr ctxt;
65
- VALUE context = rb_ivar_get(self, CONTEXT_ATTR);
66
-
67
- Data_Get_Struct(context, xmlParserCtxt, ctxt);
68
-
69
- if ((xmlParseDocument(ctxt) == -1 || !ctxt->wellFormed) && ! ctxt->recovery)
70
- {
71
- rxml_raise(&ctxt->lastError);
72
- }
73
-
74
- rb_funcall(context, rb_intern("close"), 0);
75
-
76
- return rxml_document_wrap(ctxt->myDoc);
77
- }
78
-
79
- void rxml_init_parser(void)
80
- {
81
- cXMLParser = rb_define_class_under(mXML, "Parser", rb_cObject);
82
-
83
- /* Atributes */
84
- CONTEXT_ATTR = rb_intern("@context");
85
- rb_define_attr(cXMLParser, "input", 1, 0);
86
- rb_define_attr(cXMLParser, "context", 1, 0);
87
-
88
- /* Instance Methods */
89
- rb_define_method(cXMLParser, "initialize", rxml_parser_initialize, -1);
90
- rb_define_method(cXMLParser, "parse", rxml_parser_parse, 0);
91
- }
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #include <stdarg.h>
4
+ #include "ruby_libxml.h"
5
+
6
+ /*
7
+ * Document-class: LibXML::XML::Parser
8
+ *
9
+ * The XML::Parser provides a tree based API for processing
10
+ * xml documents, in contract to XML::Reader's stream
11
+ * based api and XML::SaxParser callback based API.
12
+ *
13
+ * As a result, parsing a document creates an in-memory document object
14
+ * that consist of any number of XML::Node instances. This is simple
15
+ * and powerful model, but has the major limitation that the size of
16
+ * the document that can be processed is limited by the amount of
17
+ * memory available. In such cases, it is better to use the XML::Reader.
18
+ *
19
+ * Using the parser is simple:
20
+ *
21
+ * parser = XML::Parser.file('my_file')
22
+ * doc = parser.parse
23
+ *
24
+ * You can also parse documents (see XML::Parser.document),
25
+ * strings (see XML::Parser.string) and io objects (see
26
+ * XML::Parser.io).
27
+ */
28
+
29
+ VALUE cXMLParser;
30
+ static ID CONTEXT_ATTR;
31
+
32
+ /*
33
+ * call-seq:
34
+ * parser.initialize(context) -> XML::Parser
35
+ *
36
+ * Creates a new XML::Parser from the specified
37
+ * XML::Parser::Context.
38
+ */
39
+ static VALUE rxml_parser_initialize(int argc, VALUE *argv, VALUE self)
40
+ {
41
+ VALUE context = Qnil;
42
+
43
+ rb_scan_args(argc, argv, "01", &context);
44
+
45
+ if (context == Qnil)
46
+ {
47
+ rb_raise(rb_eArgError, "An instance of a XML::Parser::Context must be passed to XML::Parser.new");
48
+ }
49
+
50
+ rb_ivar_set(self, CONTEXT_ATTR, context);
51
+ return self;
52
+ }
53
+
54
+ /*
55
+ * call-seq:
56
+ * parser.parse -> XML::Document
57
+ *
58
+ * Parse the input XML and create an XML::Document with
59
+ * it's content. If an error occurs, XML::Parser::ParseError
60
+ * is thrown.
61
+ */
62
+ static VALUE rxml_parser_parse(VALUE self)
63
+ {
64
+ xmlParserCtxtPtr ctxt;
65
+ VALUE context = rb_ivar_get(self, CONTEXT_ATTR);
66
+
67
+ TypedData_Get_Struct(context, xmlParserCtxt, &rxml_parser_context_type, ctxt);
68
+
69
+ if ((xmlParseDocument(ctxt) == -1 || !ctxt->wellFormed) && ! ctxt->recovery)
70
+ {
71
+ rxml_raise(&ctxt->lastError);
72
+ }
73
+
74
+ rb_funcall(context, rb_intern("close"), 0);
75
+
76
+ return rxml_document_wrap(ctxt->myDoc);
77
+ }
78
+
79
+ void rxml_init_parser(void)
80
+ {
81
+ cXMLParser = rb_define_class_under(mXML, "Parser", rb_cObject);
82
+
83
+ /* Atributes */
84
+ CONTEXT_ATTR = rb_intern("@context");
85
+ rb_define_attr(cXMLParser, "input", 1, 0);
86
+ rb_define_attr(cXMLParser, "context", 1, 0);
87
+
88
+ /* Instance Methods */
89
+ rb_define_method(cXMLParser, "initialize", rxml_parser_initialize, -1);
90
+ rb_define_method(cXMLParser, "parse", rxml_parser_parse, 0);
91
+ }