libxml-ruby 2.0.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/HISTORY +516 -0
  2. data/LICENSE +23 -0
  3. data/MANIFEST +165 -0
  4. data/README.rdoc +161 -0
  5. data/Rakefile +82 -0
  6. data/ext/libxml/extconf.rb +122 -0
  7. data/ext/libxml/libxml.c +93 -0
  8. data/ext/libxml/ruby_libxml.h +101 -0
  9. data/ext/libxml/ruby_xml.c +893 -0
  10. data/ext/libxml/ruby_xml.h +10 -0
  11. data/ext/libxml/ruby_xml_attr.c +352 -0
  12. data/ext/libxml/ruby_xml_attr.h +14 -0
  13. data/ext/libxml/ruby_xml_attr_decl.c +171 -0
  14. data/ext/libxml/ruby_xml_attr_decl.h +13 -0
  15. data/ext/libxml/ruby_xml_attributes.c +277 -0
  16. data/ext/libxml/ruby_xml_attributes.h +17 -0
  17. data/ext/libxml/ruby_xml_cbg.c +85 -0
  18. data/ext/libxml/ruby_xml_document.c +958 -0
  19. data/ext/libxml/ruby_xml_document.h +17 -0
  20. data/ext/libxml/ruby_xml_dtd.c +257 -0
  21. data/ext/libxml/ruby_xml_dtd.h +9 -0
  22. data/ext/libxml/ruby_xml_encoding.c +221 -0
  23. data/ext/libxml/ruby_xml_encoding.h +16 -0
  24. data/ext/libxml/ruby_xml_error.c +1004 -0
  25. data/ext/libxml/ruby_xml_error.h +14 -0
  26. data/ext/libxml/ruby_xml_html_parser.c +92 -0
  27. data/ext/libxml/ruby_xml_html_parser.h +12 -0
  28. data/ext/libxml/ruby_xml_html_parser_context.c +308 -0
  29. data/ext/libxml/ruby_xml_html_parser_context.h +12 -0
  30. data/ext/libxml/ruby_xml_html_parser_options.c +40 -0
  31. data/ext/libxml/ruby_xml_html_parser_options.h +12 -0
  32. data/ext/libxml/ruby_xml_input_cbg.c +191 -0
  33. data/ext/libxml/ruby_xml_input_cbg.h +20 -0
  34. data/ext/libxml/ruby_xml_io.c +30 -0
  35. data/ext/libxml/ruby_xml_io.h +9 -0
  36. data/ext/libxml/ruby_xml_namespace.c +170 -0
  37. data/ext/libxml/ruby_xml_namespace.h +12 -0
  38. data/ext/libxml/ruby_xml_namespaces.c +295 -0
  39. data/ext/libxml/ruby_xml_namespaces.h +11 -0
  40. data/ext/libxml/ruby_xml_node.c +1386 -0
  41. data/ext/libxml/ruby_xml_node.h +13 -0
  42. data/ext/libxml/ruby_xml_parser.c +94 -0
  43. data/ext/libxml/ruby_xml_parser.h +14 -0
  44. data/ext/libxml/ruby_xml_parser_context.c +982 -0
  45. data/ext/libxml/ruby_xml_parser_context.h +12 -0
  46. data/ext/libxml/ruby_xml_parser_options.c +68 -0
  47. data/ext/libxml/ruby_xml_parser_options.h +14 -0
  48. data/ext/libxml/ruby_xml_reader.c +1057 -0
  49. data/ext/libxml/ruby_xml_reader.h +14 -0
  50. data/ext/libxml/ruby_xml_relaxng.c +111 -0
  51. data/ext/libxml/ruby_xml_relaxng.h +10 -0
  52. data/ext/libxml/ruby_xml_sax2_handler.c +334 -0
  53. data/ext/libxml/ruby_xml_sax2_handler.h +12 -0
  54. data/ext/libxml/ruby_xml_sax_parser.c +136 -0
  55. data/ext/libxml/ruby_xml_sax_parser.h +12 -0
  56. data/ext/libxml/ruby_xml_schema.c +159 -0
  57. data/ext/libxml/ruby_xml_schema.h +11 -0
  58. data/ext/libxml/ruby_xml_version.h +9 -0
  59. data/ext/libxml/ruby_xml_xinclude.c +18 -0
  60. data/ext/libxml/ruby_xml_xinclude.h +13 -0
  61. data/ext/libxml/ruby_xml_xpath.c +107 -0
  62. data/ext/libxml/ruby_xml_xpath.h +12 -0
  63. data/ext/libxml/ruby_xml_xpath_context.c +390 -0
  64. data/ext/libxml/ruby_xml_xpath_context.h +11 -0
  65. data/ext/libxml/ruby_xml_xpath_expression.c +83 -0
  66. data/ext/libxml/ruby_xml_xpath_expression.h +12 -0
  67. data/ext/libxml/ruby_xml_xpath_object.c +336 -0
  68. data/ext/libxml/ruby_xml_xpath_object.h +19 -0
  69. data/ext/libxml/ruby_xml_xpointer.c +101 -0
  70. data/ext/libxml/ruby_xml_xpointer.h +13 -0
  71. data/ext/mingw/Rakefile +34 -0
  72. data/ext/mingw/build.rake +41 -0
  73. data/ext/vc/libxml_ruby.sln +26 -0
  74. data/lib/1.8/libxml_ruby.so +0 -0
  75. data/lib/1.9/libxml_ruby.so +0 -0
  76. data/lib/libxml.rb +30 -0
  77. data/lib/libxml/attr.rb +113 -0
  78. data/lib/libxml/attr_decl.rb +80 -0
  79. data/lib/libxml/attributes.rb +14 -0
  80. data/lib/libxml/document.rb +192 -0
  81. data/lib/libxml/error.rb +90 -0
  82. data/lib/libxml/hpricot.rb +78 -0
  83. data/lib/libxml/html_parser.rb +96 -0
  84. data/lib/libxml/namespace.rb +62 -0
  85. data/lib/libxml/namespaces.rb +38 -0
  86. data/lib/libxml/node.rb +399 -0
  87. data/lib/libxml/ns.rb +22 -0
  88. data/lib/libxml/parser.rb +367 -0
  89. data/lib/libxml/properties.rb +23 -0
  90. data/lib/libxml/reader.rb +29 -0
  91. data/lib/libxml/sax_callbacks.rb +180 -0
  92. data/lib/libxml/sax_parser.rb +58 -0
  93. data/lib/libxml/tree.rb +29 -0
  94. data/lib/libxml/xpath_object.rb +16 -0
  95. data/lib/xml.rb +16 -0
  96. data/lib/xml/libxml.rb +10 -0
  97. data/libxml-ruby.gemspec +50 -0
  98. data/script/benchmark/depixelate +634 -0
  99. data/script/benchmark/hamlet.xml +9055 -0
  100. data/script/benchmark/parsecount +170 -0
  101. data/script/benchmark/sock_entries.xml +507 -0
  102. data/script/benchmark/throughput +41 -0
  103. data/script/test +6 -0
  104. data/setup.rb +1585 -0
  105. data/test/etc_doc_to_s.rb +21 -0
  106. data/test/ets_doc_file.rb +17 -0
  107. data/test/ets_doc_to_s.rb +23 -0
  108. data/test/ets_gpx.rb +28 -0
  109. data/test/ets_node_gc.rb +23 -0
  110. data/test/ets_test.xml +2 -0
  111. data/test/ets_tsr.rb +11 -0
  112. data/test/model/atom.xml +13 -0
  113. data/test/model/bands.iso-8859-1.xml +5 -0
  114. data/test/model/bands.utf-8.xml +5 -0
  115. data/test/model/bands.xml +5 -0
  116. data/test/model/books.xml +146 -0
  117. data/test/model/merge_bug_data.xml +58 -0
  118. data/test/model/ruby-lang.html +238 -0
  119. data/test/model/rubynet.xml +79 -0
  120. data/test/model/rubynet_project +1 -0
  121. data/test/model/shiporder.rnc +28 -0
  122. data/test/model/shiporder.rng +86 -0
  123. data/test/model/shiporder.xml +23 -0
  124. data/test/model/shiporder.xsd +31 -0
  125. data/test/model/soap.xml +27 -0
  126. data/test/model/xinclude.xml +5 -0
  127. data/test/rb-magic-comment.rb +33 -0
  128. data/test/tc_attr.rb +181 -0
  129. data/test/tc_attr_decl.rb +133 -0
  130. data/test/tc_attributes.rb +135 -0
  131. data/test/tc_deprecated_require.rb +13 -0
  132. data/test/tc_document.rb +119 -0
  133. data/test/tc_document_write.rb +187 -0
  134. data/test/tc_dtd.rb +125 -0
  135. data/test/tc_error.rb +138 -0
  136. data/test/tc_html_parser.rb +140 -0
  137. data/test/tc_namespace.rb +62 -0
  138. data/test/tc_namespaces.rb +177 -0
  139. data/test/tc_node.rb +258 -0
  140. data/test/tc_node_cdata.rb +51 -0
  141. data/test/tc_node_comment.rb +33 -0
  142. data/test/tc_node_copy.rb +42 -0
  143. data/test/tc_node_edit.rb +160 -0
  144. data/test/tc_node_text.rb +71 -0
  145. data/test/tc_node_write.rb +108 -0
  146. data/test/tc_node_xlink.rb +29 -0
  147. data/test/tc_parser.rb +336 -0
  148. data/test/tc_parser_context.rb +189 -0
  149. data/test/tc_properties.rb +39 -0
  150. data/test/tc_reader.rb +298 -0
  151. data/test/tc_relaxng.rb +54 -0
  152. data/test/tc_sax_parser.rb +276 -0
  153. data/test/tc_schema.rb +53 -0
  154. data/test/tc_traversal.rb +222 -0
  155. data/test/tc_xinclude.rb +21 -0
  156. data/test/tc_xml.rb +226 -0
  157. data/test/tc_xpath.rb +195 -0
  158. data/test/tc_xpath_context.rb +80 -0
  159. data/test/tc_xpath_expression.rb +38 -0
  160. data/test/tc_xpointer.rb +74 -0
  161. data/test/test_helper.rb +14 -0
  162. data/test/test_suite.rb +39 -0
  163. metadata +254 -0
@@ -0,0 +1,295 @@
1
+ /* $Id: ruby_xml_ns.c 660 2008-12-02 08:52:06Z cfis $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "ruby_libxml.h"
6
+ #include "ruby_xml_namespaces.h"
7
+
8
+ VALUE cXMLNamespaces;
9
+
10
+ /* Document-class: LibXML::XML::Namespaces
11
+ *
12
+ * The XML::Namespaces class is used to access information about
13
+ * a node's namespaces. For each node, libxml maintains:
14
+ *
15
+ * * The node's namespace (#namespace)
16
+ * * Which namespaces are defined on the node (#definnitions)
17
+ * * Which namespaces are in scope for the node (#each)
18
+ *
19
+ * Let's look at an example:
20
+ *
21
+ * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
22
+ * xmlns:xsd="http://www.w3.org/2001/XMLSchema">
23
+ * <soap:Body>
24
+ * <order xmlns="http://mynamespace.com"/>
25
+ * </soap:Body>
26
+ * </soap>
27
+ *
28
+ * The Envelope node is in the soap namespace. It contains
29
+ * two namespace definitions, one for soap and one for xsd.
30
+ *
31
+ * The Body node is also in the soap namespace and does not
32
+ * contain any namespaces. However, the soap and xsd namespaces
33
+ * are both in context.
34
+ *
35
+ * The order node is in its default namespace and contains
36
+ * one namespace definition (http://mynamespace.com). There
37
+ * are three namespaces in context soap, xsd and the
38
+ * default namespace.
39
+ */
40
+
41
+ static VALUE rxml_namespaces_alloc(VALUE klass)
42
+ {
43
+ return Data_Wrap_Struct(klass, NULL, NULL, NULL);
44
+ }
45
+
46
+ /*
47
+ * call-seq:
48
+ * initialize(XML::Node) -> XML::Namespaces
49
+ *
50
+ * Creates a new namespaces object. Generally you
51
+ * do not call this method directly, but instead
52
+ * access a namespaces object via XML::Node#namespaces.
53
+ *
54
+ * Usage:
55
+ *
56
+ * doc = XML::Document.string('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>')
57
+ * namespaces = new XML::Namespaces(doc.root)
58
+ */
59
+ static VALUE rxml_namespaces_initialize(VALUE self, VALUE node)
60
+ {
61
+ xmlNodePtr xnode;
62
+
63
+ Check_Type(node, T_DATA);
64
+ Data_Get_Struct(node, xmlNode, xnode);
65
+
66
+ DATA_PTR(self) = xnode;
67
+ return self;
68
+ }
69
+
70
+ /*
71
+ * call-seq:
72
+ * namespaces.definitions -> [XML::Namespace, XML::Namespace]
73
+ *
74
+ * Returns an array of XML::Namespace objects that are
75
+ * defined on this node.
76
+ *
77
+ * Usage:
78
+ *
79
+ * doc = XML::Document.string('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>')
80
+ * defs = doc.root.namespaces.definitions
81
+ */
82
+ static VALUE rxml_namespaces_definitions(VALUE self)
83
+ {
84
+ xmlNodePtr xnode;
85
+ xmlNsPtr xns;
86
+ VALUE arr;
87
+
88
+ Data_Get_Struct(self, xmlNode, xnode);
89
+
90
+ arr = rb_ary_new();
91
+ xns = xnode->nsDef;
92
+
93
+ while (xns)
94
+ {
95
+ VALUE anamespace = rxml_namespace_wrap(xns, NULL);
96
+ rb_ary_push(arr, anamespace);
97
+ xns = xns->next;
98
+ }
99
+
100
+ return arr;
101
+ }
102
+
103
+ /*
104
+ * call-seq:
105
+ * namespaces.each {|XML::Namespace|}
106
+ *
107
+ * Iterates over the namespace objects that are
108
+ * in context for this node.
109
+ *
110
+ * Usage:
111
+ *
112
+ * doc = XML::Document.string('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>')
113
+ * doc.root.namespaces.each do |ns|
114
+ * ..
115
+ * end
116
+ */
117
+ static VALUE rxml_namespaces_each(VALUE self)
118
+ {
119
+ xmlNodePtr xnode;
120
+ xmlNsPtr *nsList, *xns;
121
+
122
+ Data_Get_Struct(self, xmlNode, xnode);
123
+
124
+ nsList = xmlGetNsList(xnode->doc, xnode);
125
+
126
+ if (nsList == NULL)
127
+ return (Qnil);
128
+
129
+ for (xns = nsList; *xns != NULL; xns++)
130
+ {
131
+ VALUE ns = rxml_namespace_wrap(*xns, NULL);
132
+ rb_yield(ns);
133
+ }
134
+ xmlFree(nsList);
135
+
136
+ return Qnil;
137
+ }
138
+
139
+ /*
140
+ * call-seq:
141
+ * namespaces.find_by_href(href) -> XML::Namespace
142
+ *
143
+ * Searches for a namespace that has the specified href.
144
+ * The search starts at the current node and works upward
145
+ * through the node's parents. If a namespace is found,
146
+ * then an XML::Namespace instance is returned, otherwise nil
147
+ * is returned.
148
+ *
149
+ * Usage:
150
+ *
151
+ * doc = XML::Document.string('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>')
152
+ * ns = doc.root.namespaces.find_by_href('http://schemas.xmlsoap.org/soap/envelope/')
153
+ * assert_equal('soap', ns.prefix)
154
+ * assert_equal('http://schemas.xmlsoap.org/soap/envelope/', ns.href)
155
+ */
156
+ static VALUE rxml_namespaces_find_by_href(VALUE self, VALUE href)
157
+ {
158
+ xmlNodePtr xnode;
159
+ xmlNsPtr xns;
160
+
161
+ Check_Type(href, T_STRING);
162
+ Data_Get_Struct(self, xmlNode, xnode);
163
+
164
+ xns = xmlSearchNsByHref(xnode->doc, xnode, (xmlChar*) StringValuePtr(href));
165
+ if (xns)
166
+ return rxml_namespace_wrap(xns, NULL);
167
+ else
168
+ return Qnil;
169
+ }
170
+
171
+ /*
172
+ * call-seq:
173
+ * namespaces.find_by_prefix(prefix=nil) -> XML::Namespace
174
+ *
175
+ * Searches for a namespace that has the specified prefix.
176
+ * The search starts at the current node and works upward
177
+ * through the node's parents. If a namespace is found,
178
+ * then an XML::Namespace instance is returned, otherwise nil
179
+ * is returned.
180
+ *
181
+ * Usage:
182
+ *
183
+ * doc = XML::Document.string('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>')
184
+ * ns = doc.root.namespaces.find_by_prefix('soap')
185
+ * assert_equal('soap', ns.prefix)
186
+ * assert_equal('http://schemas.xmlsoap.org/soap/envelope/', ns.href)
187
+ */
188
+ static VALUE rxml_namespaces_find_by_prefix(VALUE self, VALUE prefix)
189
+ {
190
+ xmlNodePtr xnode;
191
+ xmlNsPtr xns;
192
+ xmlChar* xprefix = NULL;
193
+
194
+
195
+ if (!NIL_P(prefix))
196
+ {
197
+ Check_Type(prefix, T_STRING);
198
+ xprefix = (xmlChar*) StringValuePtr(prefix);
199
+ }
200
+
201
+ Data_Get_Struct(self, xmlNode, xnode);
202
+
203
+ xns = xmlSearchNs(xnode->doc, xnode, xprefix);
204
+ if (xns)
205
+ return rxml_namespace_wrap(xns, NULL);
206
+ else
207
+ return Qnil;
208
+ }
209
+
210
+ /*
211
+ * call-seq:
212
+ * namespaces.namespace -> XML::Namespace
213
+ *
214
+ * Returns the current node's namespace.
215
+ *
216
+ * Usage:
217
+ *
218
+ * doc = XML::Document.string('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>')
219
+ * ns = doc.root.namespaces.namespace
220
+ * assert_equal('soap', ns.prefix)
221
+ * assert_equal('http://schemas.xmlsoap.org/soap/envelope/', ns.href)
222
+ */
223
+ static VALUE rxml_namespaces_namespace_get(VALUE self)
224
+ {
225
+ xmlNodePtr xnode;
226
+ Data_Get_Struct(self, xmlNode, xnode);
227
+
228
+ if (xnode->ns)
229
+ return rxml_namespace_wrap(xnode->ns, NULL);
230
+ else
231
+ return Qnil;
232
+ }
233
+
234
+ /*
235
+ * call-seq:
236
+ * namespaces.namespace = XML::Namespace
237
+ *
238
+ * Sets the current node's namespace.
239
+ *
240
+ * Basic usage:
241
+ *
242
+ * # Create a node
243
+ * node = XML::Node.new('Envelope')
244
+ *
245
+ * # Define the soap namespace - this does *not* put the node in the namespace
246
+ * ns = XML::Namespace.new(node, 'soap', 'http://schemas.xmlsoap.org/soap/envelope/')
247
+ * assert_equal("<Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"/>", node.to_s)
248
+ *
249
+ * # Now put the node in the soap namespace, not how the string representation changes
250
+ * node.namespaces.namespace = ns
251
+ * assert_equal("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"/>", node.to_s)
252
+ */
253
+ static VALUE rxml_namespaces_namespace_set(VALUE self, VALUE ns)
254
+ {
255
+ xmlNodePtr xnode;
256
+ xmlNsPtr xns;
257
+
258
+ Data_Get_Struct(self, xmlNode, xnode);
259
+
260
+ Check_Type(ns, T_DATA);
261
+ Data_Get_Struct(ns, xmlNs, xns);
262
+
263
+ xmlSetNs(xnode, xns);
264
+ return self;
265
+ }
266
+
267
+ /*
268
+ * call-seq:
269
+ * namespaces.node -> XML::Node
270
+ *
271
+ * Returns the current node.
272
+ */
273
+ static VALUE rxml_namespaces_node_get(VALUE self)
274
+ {
275
+ xmlNodePtr xnode;
276
+ Data_Get_Struct(self, xmlNode, xnode);
277
+ return rxml_node_wrap(xnode);
278
+ }
279
+
280
+ void rxml_init_namespaces(void)
281
+ {
282
+ cXMLNamespaces = rb_define_class_under(mXML, "Namespaces", rb_cObject);
283
+ rb_include_module(cXMLNamespaces, rb_mEnumerable);
284
+
285
+ rb_define_alloc_func(cXMLNamespaces, rxml_namespaces_alloc);
286
+ rb_define_method(cXMLNamespaces, "initialize", rxml_namespaces_initialize, 1);
287
+
288
+ rb_define_method(cXMLNamespaces, "definitions", rxml_namespaces_definitions, 0);
289
+ rb_define_method(cXMLNamespaces, "each", rxml_namespaces_each, 0);
290
+ rb_define_method(cXMLNamespaces, "find_by_href", rxml_namespaces_find_by_href, 1);
291
+ rb_define_method(cXMLNamespaces, "find_by_prefix", rxml_namespaces_find_by_prefix, 1);
292
+ rb_define_method(cXMLNamespaces, "namespace", rxml_namespaces_namespace_get, 0);
293
+ rb_define_method(cXMLNamespaces, "namespace=", rxml_namespaces_namespace_set, 1);
294
+ rb_define_method(cXMLNamespaces, "node", rxml_namespaces_node_get, 0);
295
+ }
@@ -0,0 +1,11 @@
1
+ /* $Id: ruby_xml_ns.h 612 2008-11-21 08:01:29Z cfis $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __RXML_NAMESPACES__
6
+ #define __RXML_NAMESPACES__
7
+
8
+ extern VALUE cXMLNamespaces;
9
+
10
+ void rxml_init_namespaces(void);
11
+ #endif
@@ -0,0 +1,1386 @@
1
+ #include "ruby_libxml.h"
2
+ #include "ruby_xml_node.h"
3
+ #include <assert.h>
4
+
5
+ VALUE cXMLNode;
6
+
7
+ /* Document-class: LibXML::XML::Node
8
+ *
9
+ * Nodes are the primary objects that make up an XML document.
10
+ * The node class represents most node types that are found in
11
+ * an XML document (but not LibXML::XML::Attributes, see LibXML::XML::Attr).
12
+ * It exposes libxml's full API for creating, querying
13
+ * moving and deleting node objects. Many of these methods are
14
+ * documented in the DOM Level 3 specification found at:
15
+ * http://www.w3.org/TR/DOM-Level-3-Core/. */
16
+
17
+
18
+ /* Memory management:
19
+ *
20
+ * The bindings create a one-to-one mapping between libxml nodes
21
+ * and Ruby nodes. If a libxml node is wraped, its _private member
22
+ * is set with a reference to the Ruby object.
23
+ *
24
+ * When a libxml document or top level node is freed, it will free
25
+ * all its children. Thus Ruby is responsible for:
26
+ *
27
+ * * Using the mark function to keep alive any documents Ruby is
28
+ * referencing via the document or child nodes.
29
+ * * Using the mark function to keep alive any top level, free
30
+ * standing nodes Ruby is referencing via the node or its children.
31
+ *
32
+ * In general use, this will cause Ruby nodes to be freed before
33
+ * a libxml document. When a Ruby node is freed, the _private
34
+ * field is set back to null.
35
+ *
36
+ * In the sweep phase in Ruby 1.9.1, the document is freed before
37
+ * the nodes. To support that, the bindingds register a callback
38
+ * function with libxml that is called each time a node is freed.
39
+ * In that case, the data_ptr is set to null, so the bindings
40
+ * can recognize the situtation.
41
+ */
42
+
43
+ static void rxml_node_deregisterNode(xmlNodePtr xnode)
44
+ {
45
+ /* Has the node been wrapped and exposed to Ruby? */
46
+ if (xnode->_private)
47
+ {
48
+ /* Node was wrapped. Set the _private member to free and
49
+ then dislabe the dfree function so that Ruby will not
50
+ try to free the node a second time. */
51
+ VALUE node = (VALUE) xnode->_private;
52
+ RDATA(node)->data = NULL;
53
+ }
54
+ }
55
+
56
+ static void rxml_node_free(xmlNodePtr xnode)
57
+ {
58
+ /* Either the node has been created yet in initialize
59
+ or it has been freed by libxml already in Ruby's
60
+ mark phase. */
61
+ if (xnode == NULL)
62
+ return;
63
+
64
+ /* The ruby object wrapping the xml object no longer exists. */
65
+ xnode->_private = NULL;
66
+
67
+ /* Ruby is responsible for freeing this node since it
68
+ has no parent. */
69
+ if (xnode->parent == NULL)
70
+ xmlFreeNode(xnode);
71
+ }
72
+
73
+ void rxml_node_mark(xmlNodePtr xnode)
74
+ {
75
+ /* Either the node has been created yet in initialize
76
+ or it has been freed by libxml already in Ruby's
77
+ mark phase. */
78
+ if (xnode == NULL)
79
+ return;
80
+
81
+ if (xnode->doc != NULL)
82
+ rb_gc_mark((VALUE) xnode->doc->_private);
83
+
84
+ if (xnode->parent != NULL)
85
+ rb_gc_mark((VALUE) xnode->_private);
86
+ }
87
+
88
+ VALUE rxml_node_wrap(xmlNodePtr xnode)
89
+ {
90
+ /* Is the node already wrapped? */
91
+ if (xnode->_private != NULL)
92
+ {
93
+ return (VALUE) xnode->_private;
94
+ }
95
+ else
96
+ {
97
+ VALUE node = Data_Wrap_Struct(cXMLNode, rxml_node_mark, rxml_node_free, xnode);
98
+ xnode->_private = (void*) node;
99
+ return node;
100
+ }
101
+ }
102
+
103
+ static VALUE rxml_node_alloc(VALUE klass)
104
+ {
105
+ /* Ruby is responsible for freeing this node not libxml but don't set
106
+ up mark and free yet until we assign the node. */
107
+ return Data_Wrap_Struct(klass, rxml_node_mark, rxml_node_free, NULL);
108
+ }
109
+
110
+ /*
111
+ * call-seq:
112
+ * XML::Node.new_cdata(content = nil) -> XML::Node
113
+ *
114
+ * Create a new #CDATA node, optionally setting
115
+ * the node's content.
116
+ */
117
+ static VALUE rxml_node_new_cdata(int argc, VALUE *argv, VALUE klass)
118
+ {
119
+ VALUE content = Qnil;
120
+ xmlNodePtr xnode;
121
+
122
+ rb_scan_args(argc, argv, "01", &content);
123
+
124
+ if (NIL_P(content))
125
+ {
126
+ xnode = xmlNewCDataBlock(NULL, NULL, 0);
127
+ }
128
+ else
129
+ {
130
+ content = rb_obj_as_string(content);
131
+ xnode = xmlNewCDataBlock(NULL, (xmlChar*) StringValuePtr(content),
132
+ RSTRING_LEN(content));
133
+ }
134
+
135
+ if (xnode == NULL)
136
+ rxml_raise(&xmlLastError);
137
+
138
+ return rxml_node_wrap(xnode);
139
+ }
140
+
141
+ /*
142
+ * call-seq:
143
+ * XML::Node.new_comment(content = nil) -> XML::Node
144
+ *
145
+ * Create a new comment node, optionally setting
146
+ * the node's content.
147
+ *
148
+ */
149
+ static VALUE rxml_node_new_comment(int argc, VALUE *argv, VALUE klass)
150
+ {
151
+ VALUE content = Qnil;
152
+ xmlNodePtr xnode;
153
+
154
+ rb_scan_args(argc, argv, "01", &content);
155
+
156
+ if (NIL_P(content))
157
+ {
158
+ xnode = xmlNewComment(NULL);
159
+ }
160
+ else
161
+ {
162
+ content = rb_obj_as_string(content);
163
+ xnode = xmlNewComment((xmlChar*) StringValueCStr(content));
164
+ }
165
+
166
+ if (xnode == NULL)
167
+ rxml_raise(&xmlLastError);
168
+
169
+ return rxml_node_wrap(xnode);
170
+ }
171
+
172
+ /*
173
+ * call-seq:
174
+ * XML::Node.new_text(content) -> XML::Node
175
+ *
176
+ * Create a new text node.
177
+ *
178
+ */
179
+ static VALUE rxml_node_new_text(VALUE klass, VALUE content)
180
+ {
181
+ xmlNodePtr xnode;
182
+ Check_Type(content, T_STRING);
183
+ content = rb_obj_as_string(content);
184
+
185
+ xnode = xmlNewText((xmlChar*) StringValueCStr(content));
186
+
187
+ if (xnode == NULL)
188
+ rxml_raise(&xmlLastError);
189
+
190
+ return rxml_node_wrap(xnode);
191
+ }
192
+
193
+ static VALUE rxml_node_content_set(VALUE self, VALUE content);
194
+
195
+ /*
196
+ * call-seq:
197
+ * XML::Node.initialize(name, content = nil, namespace = nil) -> XML::Node
198
+ *
199
+ * Creates a new element with the specified name, content and
200
+ * namespace. The content and namespace may be nil.
201
+ */
202
+ static VALUE rxml_node_initialize(int argc, VALUE *argv, VALUE self)
203
+ {
204
+ VALUE name;
205
+ VALUE content;
206
+ VALUE ns;
207
+ xmlNodePtr xnode = NULL;
208
+ xmlNsPtr xns = NULL;
209
+
210
+ rb_scan_args(argc, argv, "12", &name, &content, &ns);
211
+
212
+ name = rb_obj_as_string(name);
213
+
214
+ if (!NIL_P(ns))
215
+ Data_Get_Struct(ns, xmlNs, xns);
216
+
217
+ xnode = xmlNewNode(xns, (xmlChar*) StringValuePtr(name));
218
+
219
+ if (xnode == NULL)
220
+ rxml_raise(&xmlLastError);
221
+
222
+ /* Link the Ruby object to the libxml object and vice-versa. */
223
+ xnode->_private = (void*) self;
224
+ DATA_PTR(self) = xnode;
225
+
226
+ if (!NIL_P(content))
227
+ rxml_node_content_set(self, content);
228
+
229
+ return self;
230
+ }
231
+
232
+ static VALUE rxml_node_modify_dom(VALUE self, VALUE target,
233
+ xmlNodePtr (*xmlFunc)(xmlNodePtr, xmlNodePtr))
234
+ {
235
+ xmlNodePtr xnode, xtarget, xresult;
236
+
237
+ if (rb_obj_is_kind_of(target, cXMLNode) == Qfalse)
238
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
239
+
240
+ Data_Get_Struct(self, xmlNode, xnode);
241
+ Data_Get_Struct(target, xmlNode, xtarget);
242
+
243
+ if (xtarget->doc != NULL && xtarget->doc != xnode->doc)
244
+ rb_raise(eXMLError, "Nodes belong to different documents. You must first import the by calling XML::Document.import");
245
+
246
+ /* This target node could be freed here. */
247
+ xresult = xmlFunc(xnode, xtarget);
248
+
249
+ if (!xresult)
250
+ rxml_raise(&xmlLastError);
251
+
252
+ /* Was the target freed? If yes, then wrap the new node */
253
+ if (xresult != xtarget)
254
+ {
255
+ RDATA(target)->data = xresult;
256
+ xresult->_private = (void*) target;
257
+ }
258
+
259
+ return target;
260
+ }
261
+
262
+ /*
263
+ * call-seq:
264
+ * node.base_uri -> "uri"
265
+ *
266
+ * Obtain this node's base URI.
267
+ */
268
+ static VALUE rxml_node_base_uri_get(VALUE self)
269
+ {
270
+ xmlNodePtr xnode;
271
+ xmlChar* base_uri;
272
+ VALUE result = Qnil;
273
+
274
+ Data_Get_Struct(self, xmlNode, xnode);
275
+
276
+ if (xnode->doc == NULL)
277
+ return (result);
278
+
279
+ base_uri = xmlNodeGetBase(xnode->doc, xnode);
280
+ if (base_uri)
281
+ {
282
+ result = rxml_str_new2((const char*) base_uri, xnode->doc ? xnode->doc->encoding : NULL);
283
+ xmlFree(base_uri);
284
+ }
285
+
286
+ return (result);
287
+ }
288
+
289
+ // TODO node_base_set should support setting back to nil
290
+
291
+ /*
292
+ * call-seq:
293
+ * node.base_uri = "uri"
294
+ *
295
+ * Set this node's base URI.
296
+ */
297
+ static VALUE rxml_node_base_uri_set(VALUE self, VALUE uri)
298
+ {
299
+ xmlNodePtr xnode;
300
+
301
+ Check_Type(uri, T_STRING);
302
+ Data_Get_Struct(self, xmlNode, xnode);
303
+ if (xnode->doc == NULL)
304
+ return (Qnil);
305
+
306
+ xmlNodeSetBase(xnode, (xmlChar*) StringValuePtr(uri));
307
+ return (Qtrue);
308
+ }
309
+
310
+ /*
311
+ * call-seq:
312
+ * node.content -> "string"
313
+ *
314
+ * Obtain this node's content as a string.
315
+ */
316
+ static VALUE rxml_node_content_get(VALUE self)
317
+ {
318
+ xmlNodePtr xnode;
319
+ xmlChar *content;
320
+ VALUE result = Qnil;
321
+
322
+ Data_Get_Struct(self, xmlNode, xnode);
323
+ content = xmlNodeGetContent(xnode);
324
+ if (content)
325
+ {
326
+ result = rxml_str_new2((const char *) content, xnode->doc ? xnode->doc->encoding : NULL);
327
+ xmlFree(content);
328
+ }
329
+
330
+ return result;
331
+ }
332
+
333
+ /*
334
+ * call-seq:
335
+ * node.content = "string"
336
+ *
337
+ * Set this node's content to the specified string.
338
+ */
339
+ static VALUE rxml_node_content_set(VALUE self, VALUE content)
340
+ {
341
+ xmlNodePtr xnode;
342
+
343
+ Check_Type(content, T_STRING);
344
+ Data_Get_Struct(self, xmlNode, xnode);
345
+ // XXX docs indicate need for escaping entites, need to be done? danj
346
+ xmlNodeSetContent(xnode, (xmlChar*) StringValuePtr(content));
347
+ return (Qtrue);
348
+ }
349
+
350
+ /*
351
+ * call-seq:
352
+ * node.content_stripped -> "string"
353
+ *
354
+ * Obtain this node's stripped content.
355
+ *
356
+ * *Deprecated*: Stripped content can be obtained via the
357
+ * +content+ method.
358
+ */
359
+ static VALUE rxml_node_content_stripped_get(VALUE self)
360
+ {
361
+ xmlNodePtr xnode;
362
+ xmlChar* content;
363
+ VALUE result = Qnil;
364
+
365
+ Data_Get_Struct(self, xmlNode, xnode);
366
+
367
+ if (!xnode->content)
368
+ return result;
369
+
370
+ content = xmlNodeGetContent(xnode);
371
+ if (content)
372
+ {
373
+ result = rxml_str_new2((const char*) content, xnode->doc ? xnode->doc->encoding : NULL);
374
+ xmlFree(content);
375
+ }
376
+ return (result);
377
+ }
378
+
379
+ /*
380
+ * call-seq:
381
+ * node.debug -> true|false
382
+ *
383
+ * Print libxml debugging information to stdout.
384
+ * Requires that libxml was compiled with debugging enabled.
385
+ */
386
+ static VALUE rxml_node_debug(VALUE self)
387
+ {
388
+ #ifdef LIBXML_DEBUG_ENABLED
389
+ xmlNodePtr xnode;
390
+ Data_Get_Struct(self, xmlNode, xnode);
391
+ xmlDebugDumpNode(NULL, xnode, 2);
392
+ return Qtrue;
393
+ #else
394
+ rb_warn("libxml was compiled without debugging support.")
395
+ return Qfalse;
396
+ #endif
397
+ }
398
+
399
+ /*
400
+ * call-seq:
401
+ * node.first -> XML::Node
402
+ *
403
+ * Returns this node's first child node if any.
404
+ */
405
+ static VALUE rxml_node_first_get(VALUE self)
406
+ {
407
+ xmlNodePtr xnode;
408
+
409
+ Data_Get_Struct(self, xmlNode, xnode);
410
+
411
+ if (xnode->children)
412
+ return (rxml_node_wrap(xnode->children));
413
+ else
414
+ return (Qnil);
415
+ }
416
+
417
+
418
+ /*
419
+ * call-seq:
420
+ * curr_node << "Some text"
421
+ * curr_node << node
422
+ *
423
+ * Add the specified text or XML::Node as a new child node to the
424
+ * current node.
425
+ *
426
+ * If the specified argument is a string, it should be a raw string
427
+ * that contains unescaped XML special characters. Entity references
428
+ * are not supported.
429
+ *
430
+ * The method will return the current node.
431
+ */
432
+ static VALUE rxml_node_content_add(VALUE self, VALUE obj)
433
+ {
434
+ xmlNodePtr xnode;
435
+ VALUE str;
436
+
437
+ Data_Get_Struct(self, xmlNode, xnode);
438
+ /* XXX This should only be legal for a CDATA type node, I think,
439
+ * resulting in a merge of content, as if a string were passed
440
+ * danj 070827
441
+ */
442
+ if (rb_obj_is_kind_of(obj, cXMLNode))
443
+ {
444
+ xmlNodePtr xtarget;
445
+ Data_Get_Struct(obj, xmlNode, xtarget);
446
+ xmlUnlinkNode(xtarget);
447
+ rxml_node_modify_dom(self, obj, xmlAddChild);
448
+ }
449
+ else
450
+ {
451
+ str = rb_obj_as_string(obj);
452
+ if (NIL_P(str) || TYPE(str) != T_STRING)
453
+ rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
454
+
455
+ xmlNodeAddContent(xnode, (xmlChar*) StringValuePtr(str));
456
+ }
457
+ return self;
458
+ }
459
+
460
+ /*
461
+ * call-seq:
462
+ * node.doc -> document
463
+ *
464
+ * Obtain the XML::Document this node belongs to.
465
+ */
466
+ static VALUE rxml_node_doc(VALUE self)
467
+ {
468
+ xmlNodePtr xnode;
469
+ xmlDocPtr doc = NULL;
470
+
471
+ Data_Get_Struct(self, xmlNode, xnode);
472
+
473
+ switch (xnode->type)
474
+ {
475
+ case XML_DOCUMENT_NODE:
476
+ #ifdef LIBXML_DOCB_ENABLED
477
+ case XML_DOCB_DOCUMENT_NODE:
478
+ #endif
479
+ case XML_HTML_DOCUMENT_NODE:
480
+ doc = NULL;
481
+ break;
482
+ case XML_ATTRIBUTE_NODE:
483
+ {
484
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
485
+ doc = attr->doc;
486
+ break;
487
+ }
488
+ case XML_NAMESPACE_DECL:
489
+ doc = NULL;
490
+ break;
491
+ default:
492
+ doc = xnode->doc;
493
+ break;
494
+ }
495
+
496
+ if (doc == NULL)
497
+ return (Qnil);
498
+
499
+ if (doc->_private == NULL)
500
+ rb_raise(rb_eRuntimeError, "existing document object has no ruby-instance");
501
+
502
+ return (VALUE) doc->_private;
503
+ }
504
+
505
+ /*
506
+ * call-seq:
507
+ * node.to_s -> "string"
508
+ * node.to_s(:indent => true, :encoding => 'UTF-8', :level => 0) -> "string"
509
+ *
510
+ * Converts a node, and all of its children, to a string representation.
511
+ * To include only the node's children, use the the XML::Node#inner_xml
512
+ * method.
513
+ *
514
+ * You may provide an optional hash table to control how the string is
515
+ * generated. Valid options are:
516
+ *
517
+ * :indent - Specifies if the string should be indented. The default value
518
+ * is true. Note that indentation is only added if both :indent is
519
+ * true and XML.indent_tree_output is true. If :indent is set to false,
520
+ * then both indentation and line feeds are removed from the result.
521
+ *
522
+ * :level - Specifies the indentation level. The amount of indentation
523
+ * is equal to the (level * number_spaces) + number_spaces, where libxml
524
+ * defaults the number of spaces to 2. Thus a level of 0 results in
525
+ * 2 spaces, level 1 results in 4 spaces, level 2 results in 6 spaces, etc.
526
+ *
527
+ * :encoding - Specifies the output encoding of the string. It
528
+ * defaults to XML::Encoding::UTF8. To change it, use one of the
529
+ * XML::Encoding encoding constants. */
530
+
531
+ static VALUE rxml_node_to_s(int argc, VALUE *argv, VALUE self)
532
+ {
533
+ VALUE result = Qnil;
534
+ VALUE options = Qnil;
535
+ xmlNodePtr xnode;
536
+ xmlCharEncodingHandlerPtr encodingHandler;
537
+ xmlOutputBufferPtr output;
538
+
539
+ int level = 0;
540
+ int indent = 1;
541
+ const char *xencoding = "UTF-8";
542
+
543
+ rb_scan_args(argc, argv, "01", &options);
544
+
545
+ if (!NIL_P(options))
546
+ {
547
+ VALUE rencoding, rindent, rlevel;
548
+ Check_Type(options, T_HASH);
549
+ rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
550
+ rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
551
+ rlevel = rb_hash_aref(options, ID2SYM(rb_intern("level")));
552
+
553
+ if (rindent == Qfalse)
554
+ indent = 0;
555
+
556
+ if (rlevel != Qnil)
557
+ level = NUM2INT(rlevel);
558
+
559
+ if (rencoding != Qnil)
560
+ {
561
+ xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
562
+ if (!xencoding)
563
+ rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
564
+ }
565
+ }
566
+
567
+ encodingHandler = xmlFindCharEncodingHandler(xencoding);
568
+ output = xmlAllocOutputBuffer(encodingHandler);
569
+
570
+ Data_Get_Struct(self, xmlNode, xnode);
571
+ xmlNodeDumpOutput(output, xnode->doc, xnode, level, indent, xencoding);
572
+ xmlOutputBufferFlush(output);
573
+
574
+ if (output->conv)
575
+ result = rxml_str_new2((const char*) output->conv->content, xencoding);
576
+ else
577
+ result = rxml_str_new2((const char*) output->buffer->content, xencoding);
578
+
579
+ xmlOutputBufferClose(output);
580
+
581
+ return result;
582
+ }
583
+
584
+
585
+ /*
586
+ * call-seq:
587
+ * node.each -> XML::Node
588
+ *
589
+ * Iterates over this node's children, including text
590
+ * nodes, element nodes, etc. If you wish to iterate
591
+ * only over child elements, use XML::Node#each_element.
592
+ *
593
+ * doc = XML::Document.new('model/books.xml')
594
+ * doc.root.each {|node| puts node}
595
+ */
596
+ static VALUE rxml_node_each(VALUE self)
597
+ {
598
+ xmlNodePtr xnode;
599
+ xmlNodePtr xcurrent;
600
+ Data_Get_Struct(self, xmlNode, xnode);
601
+
602
+ xcurrent = xnode->children;
603
+
604
+ while (xcurrent)
605
+ {
606
+ /* The user could remove this node, so first stache
607
+ away the next node. */
608
+ xmlNodePtr xnext = xcurrent->next;
609
+
610
+ rb_yield(rxml_node_wrap(xcurrent));
611
+ xcurrent = xnext;
612
+ }
613
+ return Qnil;
614
+ }
615
+
616
+ /*
617
+ * call-seq:
618
+ * node.empty? -> (true|false)
619
+ *
620
+ * Determine whether this node is empty.
621
+ */
622
+ static VALUE rxml_node_empty_q(VALUE self)
623
+ {
624
+ xmlNodePtr xnode;
625
+ Data_Get_Struct(self, xmlNode, xnode);
626
+ if (xnode == NULL)
627
+ return (Qnil);
628
+
629
+ return ((xmlIsBlankNode(xnode) == 1) ? Qtrue : Qfalse);
630
+ }
631
+
632
+
633
+ /*
634
+ * call-seq:
635
+ * node.eql?(other_node) => (true|false)
636
+ *
637
+ * Test equality between the two nodes. Two nodes are equal
638
+ * if they are the same node or have the same XML representation.*/
639
+ static VALUE rxml_node_eql_q(VALUE self, VALUE other)
640
+ {
641
+ if(self == other)
642
+ {
643
+ return Qtrue;
644
+ }
645
+ else if (NIL_P(other))
646
+ {
647
+ return Qfalse;
648
+ }
649
+ else
650
+ {
651
+ VALUE self_xml;
652
+ VALUE other_xml;
653
+
654
+ if (rb_obj_is_kind_of(other, cXMLNode) == Qfalse)
655
+ rb_raise(rb_eTypeError, "Nodes can only be compared against other nodes");
656
+
657
+ self_xml = rxml_node_to_s(0, NULL, self);
658
+ other_xml = rxml_node_to_s(0, NULL, other);
659
+ return(rb_funcall(self_xml, rb_intern("=="), 1, other_xml));
660
+ }
661
+ }
662
+
663
+ /*
664
+ * call-seq:
665
+ * node.lang -> "string"
666
+ *
667
+ * Obtain the language set for this node, if any.
668
+ * This is set in XML via the xml:lang attribute.
669
+ */
670
+ static VALUE rxml_node_lang_get(VALUE self)
671
+ {
672
+ xmlNodePtr xnode;
673
+ xmlChar *lang;
674
+ VALUE result = Qnil;
675
+
676
+ Data_Get_Struct(self, xmlNode, xnode);
677
+ lang = xmlNodeGetLang(xnode);
678
+
679
+ if (lang)
680
+ {
681
+ result = rxml_str_new2((const char*) lang, xnode->doc ? xnode->doc->encoding : NULL);
682
+ xmlFree(lang);
683
+ }
684
+
685
+ return (result);
686
+ }
687
+
688
+ // TODO node_lang_set should support setting back to nil
689
+
690
+ /*
691
+ * call-seq:
692
+ * node.lang = "string"
693
+ *
694
+ * Set the language for this node. This affects the value
695
+ * of the xml:lang attribute.
696
+ */
697
+ static VALUE rxml_node_lang_set(VALUE self, VALUE lang)
698
+ {
699
+ xmlNodePtr xnode;
700
+
701
+ Check_Type(lang, T_STRING);
702
+ Data_Get_Struct(self, xmlNode, xnode);
703
+ xmlNodeSetLang(xnode, (xmlChar*) StringValuePtr(lang));
704
+
705
+ return (Qtrue);
706
+ }
707
+
708
+ /*
709
+ * call-seq:
710
+ * node.last -> XML::Node
711
+ *
712
+ * Obtain the last child node of this node, if any.
713
+ */
714
+ static VALUE rxml_node_last_get(VALUE self)
715
+ {
716
+ xmlNodePtr xnode;
717
+
718
+ Data_Get_Struct(self, xmlNode, xnode);
719
+
720
+ if (xnode->last)
721
+ return (rxml_node_wrap(xnode->last));
722
+ else
723
+ return (Qnil);
724
+ }
725
+
726
+ /*
727
+ * call-seq:
728
+ * node.line_num -> num
729
+ *
730
+ * Obtain the line number (in the XML document) that this
731
+ * node was read from. If +default_line_numbers+ is set
732
+ * false (the default), this method returns zero.
733
+ */
734
+ static VALUE rxml_node_line_num(VALUE self)
735
+ {
736
+ xmlNodePtr xnode;
737
+ long line_num;
738
+ Data_Get_Struct(self, xmlNode, xnode);
739
+
740
+ if (!xmlLineNumbersDefaultValue)
741
+ rb_warn(
742
+ "Line numbers were not retained: use XML::Parser::default_line_numbers=true");
743
+
744
+ line_num = xmlGetLineNo(xnode);
745
+ if (line_num == -1)
746
+ return (Qnil);
747
+ else
748
+ return (INT2NUM((long) line_num));
749
+ }
750
+
751
+ /*
752
+ * call-seq:
753
+ * node.xlink? -> (true|false)
754
+ *
755
+ * Determine whether this node is an xlink node.
756
+ */
757
+ static VALUE rxml_node_xlink_q(VALUE self)
758
+ {
759
+ xmlNodePtr xnode;
760
+ xlinkType xlt;
761
+
762
+ Data_Get_Struct(self, xmlNode, xnode);
763
+ xlt = xlinkIsLink(xnode->doc, xnode);
764
+
765
+ if (xlt == XLINK_TYPE_NONE)
766
+ return (Qfalse);
767
+ else
768
+ return (Qtrue);
769
+ }
770
+
771
+ /*
772
+ * call-seq:
773
+ * node.xlink_type -> num
774
+ *
775
+ * Obtain the type identifier for this xlink, if applicable.
776
+ * If this is not an xlink node (see +xlink?+), will return
777
+ * nil.
778
+ */
779
+ static VALUE rxml_node_xlink_type(VALUE self)
780
+ {
781
+ xmlNodePtr xnode;
782
+ xlinkType xlt;
783
+
784
+ Data_Get_Struct(self, xmlNode, xnode);
785
+ xlt = xlinkIsLink(xnode->doc, xnode);
786
+
787
+ if (xlt == XLINK_TYPE_NONE)
788
+ return (Qnil);
789
+ else
790
+ return (INT2NUM(xlt));
791
+ }
792
+
793
+ /*
794
+ * call-seq:
795
+ * node.xlink_type_name -> "string"
796
+ *
797
+ * Obtain the type name for this xlink, if applicable.
798
+ * If this is not an xlink node (see +xlink?+), will return
799
+ * nil.
800
+ */
801
+ static VALUE rxml_node_xlink_type_name(VALUE self)
802
+ {
803
+ xmlNodePtr xnode;
804
+ xlinkType xlt;
805
+
806
+ Data_Get_Struct(self, xmlNode, xnode);
807
+ xlt = xlinkIsLink(xnode->doc, xnode);
808
+
809
+ switch (xlt)
810
+ {
811
+ case XLINK_TYPE_NONE:
812
+ return (Qnil);
813
+ case XLINK_TYPE_SIMPLE:
814
+ return (rxml_str_new2("simple", xnode->doc ? xnode->doc->encoding : NULL));
815
+ case XLINK_TYPE_EXTENDED:
816
+ return (rxml_str_new2("extended", xnode->doc ? xnode->doc->encoding : NULL));
817
+ case XLINK_TYPE_EXTENDED_SET:
818
+ return (rxml_str_new2("extended_set", xnode->doc ? xnode->doc->encoding : NULL));
819
+ default:
820
+ rb_fatal("Unknowng xlink type, %d", xlt);
821
+ }
822
+ }
823
+
824
+ /*
825
+ * call-seq:
826
+ * node.name -> "string"
827
+ *
828
+ * Obtain this node's name.
829
+ */
830
+ static VALUE rxml_node_name_get(VALUE self)
831
+ {
832
+ xmlNodePtr xnode;
833
+ const xmlChar *name;
834
+
835
+ Data_Get_Struct(self, xmlNode, xnode);
836
+
837
+ switch (xnode->type)
838
+ {
839
+ case XML_DOCUMENT_NODE:
840
+ #ifdef LIBXML_DOCB_ENABLED
841
+ case XML_DOCB_DOCUMENT_NODE:
842
+ #endif
843
+ case XML_HTML_DOCUMENT_NODE:
844
+ {
845
+ xmlDocPtr doc = (xmlDocPtr) xnode;
846
+ name = doc->URL;
847
+ break;
848
+ }
849
+ case XML_ATTRIBUTE_NODE:
850
+ {
851
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
852
+ name = attr->name;
853
+ break;
854
+ }
855
+ case XML_NAMESPACE_DECL:
856
+ {
857
+ xmlNsPtr ns = (xmlNsPtr) xnode;
858
+ name = ns->prefix;
859
+ break;
860
+ }
861
+ default:
862
+ name = xnode->name;
863
+ break;
864
+ }
865
+
866
+ if (xnode->name == NULL)
867
+ return (Qnil);
868
+ else
869
+ return (rxml_str_new2((const char*) name, xnode->doc ? xnode->doc->encoding : NULL));
870
+ }
871
+
872
+ /*
873
+ * call-seq:
874
+ * node.name = "string"
875
+ *
876
+ * Set this node's name.
877
+ */
878
+ static VALUE rxml_node_name_set(VALUE self, VALUE name)
879
+ {
880
+ xmlNodePtr xnode;
881
+ const xmlChar *xname;
882
+
883
+ Check_Type(name, T_STRING);
884
+ Data_Get_Struct(self, xmlNode, xnode);
885
+ xname = (const xmlChar*)StringValuePtr(name);
886
+
887
+ /* Note: calling xmlNodeSetName() for a text node is ignored by libXML. */
888
+ xmlNodeSetName(xnode, xname);
889
+
890
+ return (Qtrue);
891
+ }
892
+
893
+ /*
894
+ * call-seq:
895
+ * node.next -> XML::Node
896
+ *
897
+ * Returns the next sibling node if one exists.
898
+ */
899
+ static VALUE rxml_node_next_get(VALUE self)
900
+ {
901
+ xmlNodePtr xnode;
902
+
903
+ Data_Get_Struct(self, xmlNode, xnode);
904
+
905
+ if (xnode->next)
906
+ return (rxml_node_wrap(xnode->next));
907
+ else
908
+ return (Qnil);
909
+ }
910
+
911
+ /*
912
+ * call-seq:
913
+ * curr_node.next = node
914
+ *
915
+ * Adds the specified node as the next sibling of the current node.
916
+ * If the node already exists in the document, it is first removed
917
+ * from its existing context. Any adjacent text nodes will be
918
+ * merged together, meaning the returned node may be different
919
+ * than the original node.
920
+ */
921
+ static VALUE rxml_node_next_set(VALUE self, VALUE next)
922
+ {
923
+ return rxml_node_modify_dom(self, next, xmlAddNextSibling);
924
+ }
925
+
926
+ /*
927
+ * call-seq:
928
+ * node.parent -> XML::Node
929
+ *
930
+ * Obtain this node's parent node, if any.
931
+ */
932
+ static VALUE rxml_node_parent_get(VALUE self)
933
+ {
934
+ xmlNodePtr xnode;
935
+
936
+ Data_Get_Struct(self, xmlNode, xnode);
937
+
938
+ if (xnode->parent)
939
+ return (rxml_node_wrap(xnode->parent));
940
+ else
941
+ return (Qnil);
942
+ }
943
+
944
+ /*
945
+ * call-seq:
946
+ * node.path -> path
947
+ *
948
+ * Obtain this node's path.
949
+ */
950
+ static VALUE rxml_node_path(VALUE self)
951
+ {
952
+ xmlNodePtr xnode;
953
+ xmlChar *path;
954
+
955
+ Data_Get_Struct(self, xmlNode, xnode);
956
+ path = xmlGetNodePath(xnode);
957
+
958
+ if (path == NULL)
959
+ return (Qnil);
960
+ else
961
+ return (rxml_str_new2((const char*) path, xnode->doc ? xnode->doc->encoding : NULL));
962
+ }
963
+
964
+ /*
965
+ * call-seq:
966
+ * node.pointer -> XML::NodeSet
967
+ *
968
+ * Evaluates an XPointer expression relative to this node.
969
+ */
970
+ static VALUE rxml_node_pointer(VALUE self, VALUE xptr_str)
971
+ {
972
+ return (rxml_xpointer_point2(self, xptr_str));
973
+ }
974
+
975
+ /*
976
+ * call-seq:
977
+ * node.prev -> XML::Node
978
+ *
979
+ * Obtain the previous sibling, if any.
980
+ */
981
+ static VALUE rxml_node_prev_get(VALUE self)
982
+ {
983
+ xmlNodePtr xnode;
984
+ xmlNodePtr node;
985
+ Data_Get_Struct(self, xmlNode, xnode);
986
+
987
+ switch (xnode->type)
988
+ {
989
+ case XML_DOCUMENT_NODE:
990
+ #ifdef LIBXML_DOCB_ENABLED
991
+ case XML_DOCB_DOCUMENT_NODE:
992
+ #endif
993
+ case XML_HTML_DOCUMENT_NODE:
994
+ case XML_NAMESPACE_DECL:
995
+ node = NULL;
996
+ break;
997
+ case XML_ATTRIBUTE_NODE:
998
+ {
999
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
1000
+ node = (xmlNodePtr) attr->prev;
1001
+ }
1002
+ break;
1003
+ default:
1004
+ node = xnode->prev;
1005
+ break;
1006
+ }
1007
+
1008
+ if (node == NULL)
1009
+ return (Qnil);
1010
+ else
1011
+ return (rxml_node_wrap(node));
1012
+ }
1013
+
1014
+ /*
1015
+ * call-seq:
1016
+ * curr_node.prev = node
1017
+ *
1018
+ * Adds the specified node as the previous sibling of the current node.
1019
+ * If the node already exists in the document, it is first removed
1020
+ * from its existing context. Any adjacent text nodes will be
1021
+ * merged together, meaning the returned node may be different
1022
+ * than the original node.
1023
+ */
1024
+ static VALUE rxml_node_prev_set(VALUE self, VALUE prev)
1025
+ {
1026
+ return rxml_node_modify_dom(self, prev, xmlAddPrevSibling);
1027
+ }
1028
+
1029
+ /*
1030
+ * call-seq:
1031
+ * node.attributes -> attributes
1032
+ *
1033
+ * Returns the XML::Attributes for this node.
1034
+ */
1035
+ static VALUE rxml_node_attributes_get(VALUE self)
1036
+ {
1037
+ xmlNodePtr xnode;
1038
+
1039
+ Data_Get_Struct(self, xmlNode, xnode);
1040
+ return rxml_attributes_new(xnode);
1041
+ }
1042
+
1043
+ /*
1044
+ * call-seq:
1045
+ * node.property("name") -> "string"
1046
+ * node["name"] -> "string"
1047
+ *
1048
+ * Obtain the named pyroperty.
1049
+ */
1050
+ static VALUE rxml_node_attribute_get(VALUE self, VALUE name)
1051
+ {
1052
+ VALUE attributes = rxml_node_attributes_get(self);
1053
+ return rxml_attributes_attribute_get(attributes, name);
1054
+ }
1055
+
1056
+ /*
1057
+ * call-seq:
1058
+ * node["name"] = "string"
1059
+ *
1060
+ * Set the named property.
1061
+ */
1062
+ static VALUE rxml_node_property_set(VALUE self, VALUE name, VALUE value)
1063
+ {
1064
+ VALUE attributes = rxml_node_attributes_get(self);
1065
+ return rxml_attributes_attribute_set(attributes, name, value);
1066
+ }
1067
+
1068
+ /*
1069
+ * call-seq:
1070
+ * node.remove! -> node
1071
+ *
1072
+ * Removes this node and its children from the document tree by setting its document,
1073
+ * parent and siblings to nil. You can add the returned node back into a document.
1074
+ * Otherwise, the node will be freed once any references to it go out of scope.
1075
+ */
1076
+
1077
+ static VALUE rxml_node_remove_ex(VALUE self)
1078
+ {
1079
+ xmlNodePtr xnode, xresult;
1080
+ Data_Get_Struct(self, xmlNode, xnode);
1081
+
1082
+ /* First unlink the node from its parent. */
1083
+ xmlUnlinkNode(xnode);
1084
+
1085
+ /* Now copy the node we want to remove and make the
1086
+ current Ruby object point to it. We do this because
1087
+ a node has a number of dependencies on its parent
1088
+ document - its name (if using a dictionary), entities,
1089
+ namespaces, etc. For a node to live on its own, it
1090
+ needs to get its own copies of this information.*/
1091
+ xresult = xmlDocCopyNode(xnode, NULL, 1);
1092
+
1093
+ /* Now free the original node. */
1094
+ xmlFreeNode(xnode);
1095
+
1096
+ /* Now wrap the new node */
1097
+ RDATA(self)->data = xresult;
1098
+ xresult->_private = (void*) self;
1099
+
1100
+ /* Now return the removed node so the user can
1101
+ do something with it.*/
1102
+ return self;
1103
+ }
1104
+
1105
+ /*
1106
+ * call-seq:
1107
+ * curr_node.sibling = node
1108
+ *
1109
+ * Adds the specified node as the end of the current node's list
1110
+ * of siblings. If the node already exists in the document, it
1111
+ * is first removed from its existing context. Any adjacent text
1112
+ * nodes will be merged together, meaning the returned node may
1113
+ * be different than the original node.
1114
+ */
1115
+ static VALUE rxml_node_sibling_set(VALUE self, VALUE sibling)
1116
+ {
1117
+ return rxml_node_modify_dom(self, sibling, xmlAddSibling);
1118
+ }
1119
+
1120
+ /*
1121
+ * call-seq:
1122
+ * text_node.output_escaping? -> (true|false)
1123
+ * element_node.output_escaping? -> (true|false|nil)
1124
+ * attribute_node.output_escaping? -> (true|false|nil)
1125
+ * other_node.output_escaping? -> (nil)
1126
+ *
1127
+ * Determine whether this node escapes it's output or not.
1128
+ *
1129
+ * Text nodes return only +true+ or +false+. Element and attribute nodes
1130
+ * examine their immediate text node children to determine the value.
1131
+ * Any other type of node always returns +nil+.
1132
+ *
1133
+ * If an element or attribute node has at least one immediate child text node
1134
+ * and all the immediate text node children have the same +output_escaping?+
1135
+ * value, that value is returned. Otherwise, +nil+ is returned.
1136
+ */
1137
+ static VALUE rxml_node_output_escaping_q(VALUE self)
1138
+ {
1139
+ xmlNodePtr xnode;
1140
+ Data_Get_Struct(self, xmlNode, xnode);
1141
+
1142
+ switch (xnode->type) {
1143
+ case XML_TEXT_NODE:
1144
+ return xnode->name==xmlStringTextNoenc ? Qfalse : Qtrue;
1145
+ case XML_ELEMENT_NODE:
1146
+ case XML_ATTRIBUTE_NODE:
1147
+ {
1148
+ xmlNodePtr tmp = xnode->children;
1149
+ const xmlChar *match = NULL;
1150
+
1151
+ /* Find the first text node and use it as the reference. */
1152
+ while (tmp && tmp->type != XML_TEXT_NODE)
1153
+ tmp = tmp->next;
1154
+ if (! tmp)
1155
+ return Qnil;
1156
+ match = tmp->name;
1157
+
1158
+ /* Walk the remaining text nodes until we run out or one doesn't match. */
1159
+ while (tmp && (tmp->type != XML_TEXT_NODE || match == tmp->name))
1160
+ tmp = tmp->next;
1161
+
1162
+ /* We're left with either the mismatched node or the aggregate result. */
1163
+ return tmp ? Qnil : (match==xmlStringTextNoenc ? Qfalse : Qtrue);
1164
+ }
1165
+ break;
1166
+ default:
1167
+ return Qnil;
1168
+ }
1169
+ }
1170
+
1171
+ /*
1172
+ * call-seq:
1173
+ * text_node.output_escaping = true|false
1174
+ * element_node.output_escaping = true|false
1175
+ * attribute_node.output_escaping = true|false
1176
+ *
1177
+ * Controls whether this text node or the immediate text node children of an
1178
+ * element or attribute node escapes their output. Any other type of node
1179
+ * will simply ignore this operation.
1180
+ *
1181
+ * Text nodes which are added to an element or attribute node will be affected
1182
+ * by any previous setting of this property.
1183
+ */
1184
+ static VALUE rxml_node_output_escaping_set(VALUE self, VALUE bool)
1185
+ {
1186
+ xmlNodePtr xnode;
1187
+ Data_Get_Struct(self, xmlNode, xnode);
1188
+
1189
+ switch (xnode->type) {
1190
+ case XML_TEXT_NODE:
1191
+ xnode->name = (bool!=Qfalse && bool!=Qnil) ? xmlStringText : xmlStringTextNoenc;
1192
+ break;
1193
+ case XML_ELEMENT_NODE:
1194
+ case XML_ATTRIBUTE_NODE:
1195
+ {
1196
+ const xmlChar *name = (bool!=Qfalse && bool!=Qnil) ? xmlStringText : xmlStringTextNoenc;
1197
+ xmlNodePtr tmp;
1198
+ for (tmp = xnode->children; tmp; tmp = tmp->next)
1199
+ if (tmp->type == XML_TEXT_NODE)
1200
+ tmp->name = name;
1201
+ }
1202
+ break;
1203
+ default:
1204
+ return Qnil;
1205
+ }
1206
+
1207
+ return (bool!=Qfalse && bool!=Qnil) ? Qtrue : Qfalse;
1208
+ }
1209
+
1210
+ /*
1211
+ * call-seq:
1212
+ * node.space_preserve -> (true|false)
1213
+ *
1214
+ * Determine whether this node preserves whitespace.
1215
+ */
1216
+ static VALUE rxml_node_space_preserve_get(VALUE self)
1217
+ {
1218
+ xmlNodePtr xnode;
1219
+
1220
+ Data_Get_Struct(self, xmlNode, xnode);
1221
+ return (INT2NUM(xmlNodeGetSpacePreserve(xnode)));
1222
+ }
1223
+
1224
+ /*
1225
+ * call-seq:
1226
+ * node.space_preserve = true|false
1227
+ *
1228
+ * Control whether this node preserves whitespace.
1229
+ */
1230
+ static VALUE rxml_node_space_preserve_set(VALUE self, VALUE bool)
1231
+ {
1232
+ xmlNodePtr xnode;
1233
+ Data_Get_Struct(self, xmlNode, xnode);
1234
+
1235
+ if (TYPE(bool) == T_FALSE)
1236
+ xmlNodeSetSpacePreserve(xnode, 0);
1237
+ else
1238
+ xmlNodeSetSpacePreserve(xnode, 1);
1239
+
1240
+ return (Qnil);
1241
+ }
1242
+
1243
+ /*
1244
+ * call-seq:
1245
+ * node.type -> num
1246
+ *
1247
+ * Obtain this node's type identifier.
1248
+ */
1249
+ static VALUE rxml_node_type(VALUE self)
1250
+ {
1251
+ xmlNodePtr xnode;
1252
+ Data_Get_Struct(self, xmlNode, xnode);
1253
+ return (INT2NUM(xnode->type));
1254
+ }
1255
+
1256
+ /*
1257
+ * call-seq:
1258
+ * node.copy -> XML::Node
1259
+ *
1260
+ * Creates a copy of this node. To create a
1261
+ * shallow copy set the deep parameter to false.
1262
+ * To create a deep copy set the deep parameter
1263
+ * to true.
1264
+ *
1265
+ */
1266
+ static VALUE rxml_node_copy(VALUE self, VALUE deep)
1267
+ {
1268
+ xmlNodePtr xnode;
1269
+ xmlNodePtr xcopy;
1270
+ int recursive = (deep == Qnil || deep == Qfalse) ? 0 : 1;
1271
+ Data_Get_Struct(self, xmlNode, xnode);
1272
+
1273
+ xcopy = xmlCopyNode(xnode, recursive);
1274
+
1275
+ if (xcopy)
1276
+ return rxml_node_wrap(xcopy);
1277
+ else
1278
+ return Qnil;
1279
+ }
1280
+
1281
+ void rxml_init_node(void)
1282
+ {
1283
+ xmlDeregisterNodeDefault(rxml_node_deregisterNode);
1284
+
1285
+ cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
1286
+
1287
+ rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
1288
+ rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
1289
+ rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
1290
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
1291
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
1292
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
1293
+ rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
1294
+ rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
1295
+ rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
1296
+ rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
1297
+ rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
1298
+ rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
1299
+ rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
1300
+ rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
1301
+
1302
+ rb_define_const(cXMLNode, "ELEMENT_NODE", INT2FIX(XML_ELEMENT_NODE));
1303
+ rb_define_const(cXMLNode, "ATTRIBUTE_NODE", INT2FIX(XML_ATTRIBUTE_NODE));
1304
+ rb_define_const(cXMLNode, "TEXT_NODE", INT2FIX(XML_TEXT_NODE));
1305
+ rb_define_const(cXMLNode, "CDATA_SECTION_NODE", INT2FIX(XML_CDATA_SECTION_NODE));
1306
+ rb_define_const(cXMLNode, "ENTITY_REF_NODE", INT2FIX(XML_ENTITY_REF_NODE));
1307
+ rb_define_const(cXMLNode, "ENTITY_NODE", INT2FIX(XML_ENTITY_NODE));
1308
+ rb_define_const(cXMLNode, "PI_NODE", INT2FIX(XML_PI_NODE));
1309
+ rb_define_const(cXMLNode, "COMMENT_NODE", INT2FIX(XML_COMMENT_NODE));
1310
+ rb_define_const(cXMLNode, "DOCUMENT_NODE", INT2FIX(XML_DOCUMENT_NODE));
1311
+ rb_define_const(cXMLNode, "DOCUMENT_TYPE_NODE", INT2FIX(XML_DOCUMENT_TYPE_NODE));
1312
+ rb_define_const(cXMLNode, "DOCUMENT_FRAG_NODE", INT2FIX(XML_DOCUMENT_FRAG_NODE));
1313
+ rb_define_const(cXMLNode, "NOTATION_NODE", INT2FIX(XML_NOTATION_NODE));
1314
+ rb_define_const(cXMLNode, "HTML_DOCUMENT_NODE", INT2FIX(XML_HTML_DOCUMENT_NODE));
1315
+ rb_define_const(cXMLNode, "DTD_NODE", INT2FIX(XML_DTD_NODE));
1316
+ rb_define_const(cXMLNode, "ELEMENT_DECL", INT2FIX(XML_ELEMENT_DECL));
1317
+ rb_define_const(cXMLNode, "ATTRIBUTE_DECL", INT2FIX(XML_ATTRIBUTE_DECL));
1318
+ rb_define_const(cXMLNode, "ENTITY_DECL", INT2FIX(XML_ENTITY_DECL));
1319
+ rb_define_const(cXMLNode, "NAMESPACE_DECL", INT2FIX(XML_NAMESPACE_DECL));
1320
+ rb_define_const(cXMLNode, "XINCLUDE_START", INT2FIX(XML_XINCLUDE_START));
1321
+ rb_define_const(cXMLNode, "XINCLUDE_END", INT2FIX(XML_XINCLUDE_END));
1322
+
1323
+ #ifdef LIBXML_DOCB_ENABLED
1324
+ rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", INT2FIX(XML_DOCB_DOCUMENT_NODE));
1325
+ #else
1326
+ rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", Qnil);
1327
+ #endif
1328
+
1329
+ rb_define_singleton_method(cXMLNode, "new_cdata", rxml_node_new_cdata, -1);
1330
+ rb_define_singleton_method(cXMLNode, "new_comment", rxml_node_new_comment, -1);
1331
+ rb_define_singleton_method(cXMLNode, "new_text", rxml_node_new_text, 1);
1332
+
1333
+ /* Initialization */
1334
+ rb_define_alloc_func(cXMLNode, rxml_node_alloc);
1335
+ rb_define_method(cXMLNode, "initialize", rxml_node_initialize, -1);
1336
+
1337
+ /* Traversal */
1338
+ rb_include_module(cXMLNode, rb_mEnumerable);
1339
+ rb_define_method(cXMLNode, "[]", rxml_node_attribute_get, 1);
1340
+ rb_define_method(cXMLNode, "each", rxml_node_each, 0);
1341
+ rb_define_method(cXMLNode, "first", rxml_node_first_get, 0);
1342
+ rb_define_method(cXMLNode, "last", rxml_node_last_get, 0);
1343
+ rb_define_method(cXMLNode, "next", rxml_node_next_get, 0);
1344
+ rb_define_method(cXMLNode, "parent", rxml_node_parent_get, 0);
1345
+ rb_define_method(cXMLNode, "prev", rxml_node_prev_get, 0);
1346
+
1347
+ /* Modification */
1348
+ rb_define_method(cXMLNode, "[]=", rxml_node_property_set, 2);
1349
+ rb_define_method(cXMLNode, "<<", rxml_node_content_add, 1);
1350
+ rb_define_method(cXMLNode, "sibling=", rxml_node_sibling_set, 1);
1351
+ rb_define_method(cXMLNode, "next=", rxml_node_next_set, 1);
1352
+ rb_define_method(cXMLNode, "prev=", rxml_node_prev_set, 1);
1353
+
1354
+ /* Rest of the node api */
1355
+ rb_define_method(cXMLNode, "attributes", rxml_node_attributes_get, 0);
1356
+ rb_define_method(cXMLNode, "base_uri", rxml_node_base_uri_get, 0);
1357
+ rb_define_method(cXMLNode, "base_uri=", rxml_node_base_uri_set, 1);
1358
+ rb_define_method(cXMLNode, "blank?", rxml_node_empty_q, 0);
1359
+ rb_define_method(cXMLNode, "copy", rxml_node_copy, 1);
1360
+ rb_define_method(cXMLNode, "content", rxml_node_content_get, 0);
1361
+ rb_define_method(cXMLNode, "content=", rxml_node_content_set, 1);
1362
+ rb_define_method(cXMLNode, "content_stripped", rxml_node_content_stripped_get, 0);
1363
+ rb_define_method(cXMLNode, "debug", rxml_node_debug, 0);
1364
+ rb_define_method(cXMLNode, "doc", rxml_node_doc, 0);
1365
+ rb_define_method(cXMLNode, "empty?", rxml_node_empty_q, 0);
1366
+ rb_define_method(cXMLNode, "eql?", rxml_node_eql_q, 1);
1367
+ rb_define_method(cXMLNode, "lang", rxml_node_lang_get, 0);
1368
+ rb_define_method(cXMLNode, "lang=", rxml_node_lang_set, 1);
1369
+ rb_define_method(cXMLNode, "line_num", rxml_node_line_num, 0);
1370
+ rb_define_method(cXMLNode, "name", rxml_node_name_get, 0);
1371
+ rb_define_method(cXMLNode, "name=", rxml_node_name_set, 1);
1372
+ rb_define_method(cXMLNode, "node_type", rxml_node_type, 0);
1373
+ rb_define_method(cXMLNode, "output_escaping?", rxml_node_output_escaping_q, 0);
1374
+ rb_define_method(cXMLNode, "output_escaping=", rxml_node_output_escaping_set, 1);
1375
+ rb_define_method(cXMLNode, "path", rxml_node_path, 0);
1376
+ rb_define_method(cXMLNode, "pointer", rxml_node_pointer, 1);
1377
+ rb_define_method(cXMLNode, "remove!", rxml_node_remove_ex, 0);
1378
+ rb_define_method(cXMLNode, "space_preserve", rxml_node_space_preserve_get, 0);
1379
+ rb_define_method(cXMLNode, "space_preserve=", rxml_node_space_preserve_set, 1);
1380
+ rb_define_method(cXMLNode, "to_s", rxml_node_to_s, -1);
1381
+ rb_define_method(cXMLNode, "xlink?", rxml_node_xlink_q, 0);
1382
+ rb_define_method(cXMLNode, "xlink_type", rxml_node_xlink_type, 0);
1383
+ rb_define_method(cXMLNode, "xlink_type_name", rxml_node_xlink_type_name, 0);
1384
+
1385
+ rb_define_alias(cXMLNode, "==", "eql?");
1386
+ }