libxml-ruby 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/CHANGES +22 -0
  2. data/README +3 -1
  3. data/ext/libxml/cbg.c +86 -76
  4. data/ext/libxml/extconf.rb +2 -1
  5. data/ext/libxml/libxml.c +899 -885
  6. data/ext/libxml/ruby_libxml.h +65 -70
  7. data/ext/libxml/ruby_xml_attr.c +485 -500
  8. data/ext/libxml/ruby_xml_attributes.c +107 -106
  9. data/ext/libxml/ruby_xml_document.c +355 -356
  10. data/ext/libxml/ruby_xml_dtd.c +119 -117
  11. data/ext/libxml/ruby_xml_error.c +1112 -581
  12. data/ext/libxml/ruby_xml_html_parser.c +35 -34
  13. data/ext/libxml/ruby_xml_input.c +182 -187
  14. data/ext/libxml/ruby_xml_input_cbg.c +197 -179
  15. data/ext/libxml/ruby_xml_node.c +1529 -1566
  16. data/ext/libxml/ruby_xml_node.h +2 -2
  17. data/ext/libxml/ruby_xml_ns.c +150 -156
  18. data/ext/libxml/ruby_xml_parser.c +37 -36
  19. data/ext/libxml/ruby_xml_parser_context.c +657 -659
  20. data/ext/libxml/ruby_xml_reader.c +203 -209
  21. data/ext/libxml/ruby_xml_relaxng.c +29 -25
  22. data/ext/libxml/ruby_xml_sax_parser.c +33 -32
  23. data/ext/libxml/ruby_xml_schema.c +165 -161
  24. data/ext/libxml/ruby_xml_state.c +19 -21
  25. data/ext/libxml/ruby_xml_xinclude.c +24 -25
  26. data/ext/libxml/ruby_xml_xpath.c +108 -108
  27. data/ext/libxml/ruby_xml_xpath_context.c +305 -293
  28. data/ext/libxml/ruby_xml_xpath_expression.c +24 -24
  29. data/ext/libxml/ruby_xml_xpath_object.c +89 -96
  30. data/ext/libxml/ruby_xml_xpointer.c +107 -109
  31. data/ext/libxml/ruby_xml_xpointer.h +13 -13
  32. data/ext/libxml/version.h +2 -2
  33. data/ext/mingw/Rakefile +1 -1
  34. data/ext/vc/libxml_ruby.vcproj +1 -1
  35. data/lib/libxml/error.rb +4 -4
  36. data/test/tc_node_edit.rb +14 -2
  37. data/test/tc_node_text.rb +9 -9
  38. metadata +2 -2
@@ -1,179 +1,197 @@
1
- /* Author: Martin Povolny (xpovolny@fi.muni.cz) */
2
-
3
- #include "ruby_libxml.h"
4
- #include "ruby_xml_input_cbg.h"
5
-
6
- /* Document-class: LibXML::XML::InputCallbacks
7
- *
8
- * Support for adding custom scheme handlers. */
9
-
10
- static ic_scheme *first_scheme = 0;
11
-
12
- int ic_match (char const *filename) {
13
- ic_scheme *scheme;
14
-
15
- //fprintf( stderr, "ic_match: %s\n", filename );
16
-
17
- scheme = first_scheme;
18
- while (0 != scheme) {
19
- if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len)) {
20
- return 1;
21
- }
22
- scheme = scheme->next_scheme;
23
- }
24
- return 0;
25
- }
26
-
27
- void* ic_open (char const *filename) {
28
- ic_doc_context *ic_doc;
29
- ic_scheme *scheme;
30
- VALUE res;
31
-
32
- scheme = first_scheme;
33
- while (0 != scheme) {
34
- if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len)) {
35
- ic_doc = (ic_doc_context*)malloc( sizeof(ic_doc_context) );
36
-
37
- res = rb_funcall( scheme->class,
38
- rb_intern("document_query"),
39
- 1,
40
- rb_str_new2(filename) );
41
-
42
- ic_doc->buffer = strdup( StringValuePtr(res) );
43
-
44
- ic_doc->bpos = ic_doc->buffer;
45
- ic_doc->remaining = strlen(ic_doc->buffer);
46
- return ic_doc;
47
- }
48
- scheme = scheme->next_scheme;
49
- }
50
- return 0;
51
- }
52
-
53
- int ic_read (void *context, char *buffer, int len) {
54
- ic_doc_context *ic_doc;
55
- int ret_len;
56
- ic_doc = (ic_doc_context*)context;
57
-
58
- if (len >= ic_doc->remaining) {
59
- ret_len = ic_doc->remaining;
60
- } else {
61
- ret_len = len;
62
- }
63
- ic_doc->remaining -= ret_len;
64
- strncpy( buffer, ic_doc->bpos, ret_len );
65
- ic_doc->bpos += ret_len;
66
-
67
- return ret_len;
68
- }
69
-
70
- int ic_close (void *context) {
71
- ruby_xfree( ((ic_doc_context*)context)->buffer );
72
- ruby_xfree( context );
73
- return 1;
74
- }
75
-
76
- /*
77
- * call-seq:
78
- * register
79
- *
80
- * Register a new set of I/O callback for handling parser input.
81
- */
82
- static VALUE input_callbacks_register_input_callbacks() {
83
- xmlRegisterInputCallbacks( ic_match, ic_open, ic_read, ic_close );
84
- return(Qtrue);
85
- }
86
-
87
-
88
- /*
89
- * call-seq:
90
- * add_scheme
91
- *
92
- * No documentation available.
93
- */
94
- static VALUE
95
- input_callbacks_add_scheme (VALUE self, VALUE scheme_name, VALUE class) {
96
- ic_scheme *scheme;
97
-
98
- Check_Type(scheme_name, T_STRING);
99
-
100
- scheme = (ic_scheme*)malloc(sizeof(ic_scheme));
101
- scheme->next_scheme = 0;
102
- scheme->scheme_name = strdup(StringValuePtr(scheme_name)); /* TODO alloc, dealloc */
103
- scheme->name_len = strlen(scheme->scheme_name);
104
- scheme->class = class; /* TODO alloc, dealloc */
105
-
106
- //fprintf( stderr, "registered: %s, %d, %s\n", scheme->scheme_name, scheme->name_len, scheme->class );
107
-
108
- if (0 == first_scheme)
109
- first_scheme = scheme;
110
- else {
111
- ic_scheme *pos;
112
- pos = first_scheme;
113
- while (0 != pos->next_scheme)
114
- pos = pos->next_scheme;
115
- pos->next_scheme = scheme;
116
- }
117
-
118
- return(Qtrue);
119
- }
120
-
121
- /*
122
- * call-seq:
123
- * remove_scheme
124
- *
125
- * No documentation available.
126
- */
127
- static VALUE
128
- input_callbacks_remove_scheme (VALUE self, VALUE scheme_name) {
129
- char *name;
130
- ic_scheme *save_scheme, *scheme;
131
-
132
- Check_Type(scheme_name, T_STRING);
133
- name = StringValuePtr(scheme_name);
134
-
135
- if (0 == first_scheme)
136
- return Qfalse;
137
-
138
- if (!strncmp(name, first_scheme->scheme_name, first_scheme->name_len)) {
139
- save_scheme = first_scheme->next_scheme;
140
-
141
- ruby_xfree(first_scheme->scheme_name);
142
- ruby_xfree(first_scheme);
143
-
144
- first_scheme = save_scheme;
145
- return Qtrue;
146
- }
147
-
148
- scheme = first_scheme;
149
- while (0 != scheme->next_scheme) {
150
- if ( !strncmp( name, scheme->next_scheme->scheme_name, scheme->next_scheme->name_len ) ) {
151
- save_scheme = scheme->next_scheme->next_scheme;
152
-
153
- ruby_xfree(scheme->next_scheme->scheme_name);
154
- ruby_xfree(scheme->next_scheme);
155
-
156
- scheme->next_scheme = save_scheme;
157
- return Qtrue;
158
- }
159
- scheme = scheme->next_scheme;
160
- }
161
- return Qfalse;
162
- }
163
-
164
- // Rdoc needs to know
165
- #ifdef RDOC_NEVER_DEFINED
166
- mLibXML = rb_define_module("LibXML");
167
- mXML = rb_define_module_under(mLibXML, "XML");
168
- #endif
169
-
170
- void
171
- ruby_init_input_callbacks(void) {
172
- VALUE cInputCallbacks;
173
- cInputCallbacks = rb_define_class_under(mXML, "InputCallbacks", rb_cObject);
174
-
175
- /* Class Methods */
176
- rb_define_singleton_method(cInputCallbacks, "register", input_callbacks_register_input_callbacks, 0);
177
- rb_define_singleton_method(cInputCallbacks, "add_scheme", input_callbacks_add_scheme, 2);
178
- rb_define_singleton_method(cInputCallbacks, "remove_scheme", input_callbacks_remove_scheme, 1);
179
- }
1
+ /* Author: Martin Povolny (xpovolny@fi.muni.cz) */
2
+
3
+ #include "ruby_libxml.h"
4
+ #include "ruby_xml_input_cbg.h"
5
+
6
+ /* Document-class: LibXML::XML::InputCallbacks
7
+ *
8
+ * Support for adding custom scheme handlers. */
9
+
10
+ static ic_scheme *first_scheme = 0;
11
+
12
+ int ic_match(char const *filename)
13
+ {
14
+ ic_scheme *scheme;
15
+
16
+ //fprintf( stderr, "ic_match: %s\n", filename );
17
+
18
+ scheme = first_scheme;
19
+ while (0 != scheme)
20
+ {
21
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len))
22
+ {
23
+ return 1;
24
+ }
25
+ scheme = scheme->next_scheme;
26
+ }
27
+ return 0;
28
+ }
29
+
30
+ void* ic_open(char const *filename)
31
+ {
32
+ ic_doc_context *ic_doc;
33
+ ic_scheme *scheme;
34
+ VALUE res;
35
+
36
+ scheme = first_scheme;
37
+ while (0 != scheme)
38
+ {
39
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len))
40
+ {
41
+ ic_doc = (ic_doc_context*) malloc(sizeof(ic_doc_context));
42
+
43
+ res = rb_funcall(scheme->class, rb_intern("document_query"), 1,
44
+ rb_str_new2(filename));
45
+
46
+ ic_doc->buffer = strdup(StringValuePtr(res));
47
+
48
+ ic_doc->bpos = ic_doc->buffer;
49
+ ic_doc->remaining = strlen(ic_doc->buffer);
50
+ return ic_doc;
51
+ }
52
+ scheme = scheme->next_scheme;
53
+ }
54
+ return 0;
55
+ }
56
+
57
+ int ic_read(void *context, char *buffer, int len)
58
+ {
59
+ ic_doc_context *ic_doc;
60
+ int ret_len;
61
+ ic_doc = (ic_doc_context*) context;
62
+
63
+ if (len >= ic_doc->remaining)
64
+ {
65
+ ret_len = ic_doc->remaining;
66
+ }
67
+ else
68
+ {
69
+ ret_len = len;
70
+ }
71
+ ic_doc->remaining -= ret_len;
72
+ strncpy(buffer, ic_doc->bpos, ret_len);
73
+ ic_doc->bpos += ret_len;
74
+
75
+ return ret_len;
76
+ }
77
+
78
+ int ic_close(void *context)
79
+ {
80
+ ruby_xfree(((ic_doc_context*) context)->buffer);
81
+ ruby_xfree(context);
82
+ return 1;
83
+ }
84
+
85
+ /*
86
+ * call-seq:
87
+ * register
88
+ *
89
+ * Register a new set of I/O callback for handling parser input.
90
+ */
91
+ static VALUE input_callbacks_register_input_callbacks()
92
+ {
93
+ xmlRegisterInputCallbacks(ic_match, ic_open, ic_read, ic_close);
94
+ return (Qtrue);
95
+ }
96
+
97
+ /*
98
+ * call-seq:
99
+ * add_scheme
100
+ *
101
+ * No documentation available.
102
+ */
103
+ static VALUE input_callbacks_add_scheme(VALUE self, VALUE scheme_name,
104
+ VALUE class)
105
+ {
106
+ ic_scheme *scheme;
107
+
108
+ Check_Type(scheme_name, T_STRING);
109
+
110
+ scheme = (ic_scheme*) malloc(sizeof(ic_scheme));
111
+ scheme->next_scheme = 0;
112
+ scheme->scheme_name = strdup(StringValuePtr(scheme_name)); /* TODO alloc, dealloc */
113
+ scheme->name_len = strlen(scheme->scheme_name);
114
+ scheme->class = class; /* TODO alloc, dealloc */
115
+
116
+ //fprintf( stderr, "registered: %s, %d, %s\n", scheme->scheme_name, scheme->name_len, scheme->class );
117
+
118
+ if (0 == first_scheme)
119
+ first_scheme = scheme;
120
+ else
121
+ {
122
+ ic_scheme *pos;
123
+ pos = first_scheme;
124
+ while (0 != pos->next_scheme)
125
+ pos = pos->next_scheme;
126
+ pos->next_scheme = scheme;
127
+ }
128
+
129
+ return (Qtrue);
130
+ }
131
+
132
+ /*
133
+ * call-seq:
134
+ * remove_scheme
135
+ *
136
+ * No documentation available.
137
+ */
138
+ static VALUE input_callbacks_remove_scheme(VALUE self, VALUE scheme_name)
139
+ {
140
+ char *name;
141
+ ic_scheme *save_scheme, *scheme;
142
+
143
+ Check_Type(scheme_name, T_STRING);
144
+ name = StringValuePtr(scheme_name);
145
+
146
+ if (0 == first_scheme)
147
+ return Qfalse;
148
+
149
+ if (!strncmp(name, first_scheme->scheme_name, first_scheme->name_len))
150
+ {
151
+ save_scheme = first_scheme->next_scheme;
152
+
153
+ ruby_xfree(first_scheme->scheme_name);
154
+ ruby_xfree(first_scheme);
155
+
156
+ first_scheme = save_scheme;
157
+ return Qtrue;
158
+ }
159
+
160
+ scheme = first_scheme;
161
+ while (0 != scheme->next_scheme)
162
+ {
163
+ if (!strncmp(name, scheme->next_scheme->scheme_name,
164
+ scheme->next_scheme->name_len))
165
+ {
166
+ save_scheme = scheme->next_scheme->next_scheme;
167
+
168
+ ruby_xfree(scheme->next_scheme->scheme_name);
169
+ ruby_xfree(scheme->next_scheme);
170
+
171
+ scheme->next_scheme = save_scheme;
172
+ return Qtrue;
173
+ }
174
+ scheme = scheme->next_scheme;
175
+ }
176
+ return Qfalse;
177
+ }
178
+
179
+ // Rdoc needs to know
180
+ #ifdef RDOC_NEVER_DEFINED
181
+ mLibXML = rb_define_module("LibXML");
182
+ mXML = rb_define_module_under(mLibXML, "XML");
183
+ #endif
184
+
185
+ void ruby_init_input_callbacks(void)
186
+ {
187
+ VALUE cInputCallbacks;
188
+ cInputCallbacks = rb_define_class_under(mXML, "InputCallbacks", rb_cObject);
189
+
190
+ /* Class Methods */
191
+ rb_define_singleton_method(cInputCallbacks, "register",
192
+ input_callbacks_register_input_callbacks, 0);
193
+ rb_define_singleton_method(cInputCallbacks, "add_scheme",
194
+ input_callbacks_add_scheme, 2);
195
+ rb_define_singleton_method(cInputCallbacks, "remove_scheme",
196
+ input_callbacks_remove_scheme, 1);
197
+ }
@@ -1,1566 +1,1529 @@
1
- /* $Id: ruby_xml_node.c 612 2008-11-21 08:01:29Z cfis $ */
2
-
3
- /* Please see the LICENSE file for copyright and distribution information */
4
-
5
- #include "ruby_libxml.h"
6
- #include "ruby_xml_node.h"
7
-
8
- VALUE cXMLNode;
9
-
10
- /* Document-class: LibXML::XML::Node
11
- *
12
- * Nodes are the primary objects that make up an XML document.
13
- * The node class represents most node types that are found in
14
- * an XML document (but not Attributes, see LibXML::XML::Attribute).
15
- * It exposes libxml's full API for creating, querying
16
- * moving and deleting node objects. Many of these methods are
17
- * documented in the DOM Level 3 specification found at:
18
- * http://www.w3.org/TR/DOM-Level-3-Core/. */
19
-
20
-
21
- VALUE
22
- check_string_or_symbol( VALUE val ) {
23
- if( TYPE(val) != T_STRING && TYPE(val) != T_SYMBOL ) {
24
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Symbol)",
25
- rb_obj_classname(val) );
26
- }
27
- return rb_obj_as_string( val );
28
- }
29
-
30
-
31
- /*
32
- * call-seq:
33
- * node.base -> "uri"
34
- *
35
- * Obtain this node's base URI.
36
- */
37
- static VALUE
38
- rxml_node_base_get(VALUE self) {
39
- xmlNodePtr xnode;
40
- xmlChar* base_uri;
41
- VALUE result = Qnil;
42
-
43
- Data_Get_Struct(self, xmlNode, xnode);
44
-
45
- if (xnode->doc == NULL)
46
- return(result);
47
-
48
- base_uri = xmlNodeGetBase(xnode->doc, xnode);
49
- if (base_uri) {
50
- result = rb_str_new2((const char*)base_uri);
51
- xmlFree(base_uri);
52
- }
53
-
54
- return(result);
55
- }
56
-
57
-
58
- // TODO node_base_set should support setting back to nil
59
-
60
- /*
61
- * call-seq:
62
- * node.base = "uri"
63
- *
64
- * Set this node's base URI.
65
- */
66
- static VALUE
67
- rxml_node_base_set(VALUE self, VALUE uri) {
68
- xmlNodePtr xnode;
69
-
70
- Check_Type(uri, T_STRING);
71
- Data_Get_Struct(self, xmlNode, xnode);
72
- if (xnode->doc == NULL)
73
- return(Qnil);
74
-
75
- xmlNodeSetBase(xnode, (xmlChar*)StringValuePtr(uri));
76
- return(Qtrue);
77
- }
78
-
79
-
80
- /*
81
- * call-seq:
82
- * node.content -> "string"
83
- *
84
- * Obtain this node's content as a string.
85
- */
86
- static VALUE
87
- rxml_node_content_get(VALUE self) {
88
- xmlNodePtr xnode;
89
- xmlChar *content;
90
- VALUE result = Qnil;
91
-
92
- Data_Get_Struct(self, xmlNode, xnode);
93
- content = xmlNodeGetContent(xnode);
94
- if (content) {
95
- result = rb_str_new2((const char *) content);
96
- xmlFree(content);
97
- }
98
-
99
- return result;
100
- }
101
-
102
- /*
103
- * call-seq:
104
- * node.content = "string"
105
- *
106
- * Set this node's content to the specified string.
107
- */
108
- static VALUE
109
- rxml_node_content_set(VALUE self, VALUE content) {
110
- xmlNodePtr xnode;
111
-
112
- Check_Type(content, T_STRING);
113
- Data_Get_Struct(self, xmlNode, xnode);
114
- // XXX docs indicate need for escaping entites, need to be done? danj
115
- xmlNodeSetContent(xnode, (xmlChar*)StringValuePtr(content));
116
- return(Qtrue);
117
- }
118
-
119
-
120
- /*
121
- * call-seq:
122
- * node.content_stripped -> "string"
123
- *
124
- * Obtain this node's stripped content.
125
- *
126
- * *Deprecated*: Stripped content can be obtained via the
127
- * +content+ method.
128
- */
129
- static VALUE
130
- rxml_node_content_stripped_get(VALUE self) {
131
- xmlNodePtr xnode;
132
- xmlChar* content;
133
- VALUE result = Qnil;
134
-
135
- Data_Get_Struct(self, xmlNode, xnode);
136
-
137
- if (!xnode->content)
138
- return result;
139
-
140
- content = xmlNodeGetContent(xnode);
141
- if (content) {
142
- result = rb_str_new2((const char*)content);
143
- xmlFree(content);
144
- }
145
- return(result);
146
- }
147
-
148
- /*
149
- * call-seq:
150
- * node.first -> XML::Node
151
- *
152
- * Returns this node's first child node if any.
153
- */
154
- static VALUE
155
- rxml_node_first_get(VALUE self) {
156
- xmlNodePtr xnode;
157
-
158
- Data_Get_Struct(self, xmlNode, xnode);
159
-
160
- if (xnode->children)
161
- return(rxml_node2_wrap(cXMLNode, xnode->children));
162
- else
163
- return(Qnil);
164
- }
165
-
166
-
167
- /*
168
- * underlying for child_set and child_add, difference being
169
- * former raises on implicit copy, latter does not.
170
- */
171
- static VALUE
172
- rxml_node_child_set_aux(VALUE self, VALUE rnode) {
173
- xmlNodePtr pnode, chld, ret;
174
-
175
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
176
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
177
-
178
- Data_Get_Struct(self, xmlNode, pnode);
179
- Data_Get_Struct(rnode, xmlNode, chld);
180
-
181
- if ( chld->parent != NULL || chld->doc != NULL )
182
- rb_raise(rb_eRuntimeError, "Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
183
-
184
- ret = xmlAddChild(pnode, chld);
185
- if (ret == NULL) {
186
- rxml_raise(&xmlLastError);
187
- } else if ( ret==chld ) {
188
- /* child was added whole to parent and we need to return it as a new object */
189
- return rxml_node2_wrap(cXMLNode,chld);
190
- }
191
- /* else */
192
- /* If it was a text node, then ret should be parent->last, so we will just return ret. */
193
- return rxml_node2_wrap(cXMLNode,ret);
194
- }
195
-
196
- /*
197
- * call-seq:
198
- * node.child = node
199
- *
200
- * Set a child node for this node. Also called for <<
201
- */
202
- static VALUE
203
- rxml_node_child_set(VALUE self, VALUE rnode) {
204
- return rxml_node_child_set_aux(self, rnode);
205
- }
206
-
207
-
208
- /*
209
- * call-seq:
210
- * node << ("string" | node) -> XML::Node
211
- *
212
- * Add the specified string or XML::Node to this node's
213
- * content. The returned node is the node that was
214
- * added and not self, thereby allowing << calls to
215
- * be chained.
216
- */
217
- static VALUE
218
- rxml_node_content_add(VALUE self, VALUE obj) {
219
- xmlNodePtr xnode;
220
- VALUE str;
221
-
222
- Data_Get_Struct(self, xmlNode, xnode);
223
- /* XXX This should only be legal for a CDATA type node, I think,
224
- * resulting in a merge of content, as if a string were passed
225
- * danj 070827
226
- */
227
- if (rb_obj_is_kind_of(obj, cXMLNode)) {
228
- rxml_node_child_set(self, obj);
229
- } else {
230
- str = rb_obj_as_string(obj);
231
- if (NIL_P(str) || TYPE(str) != T_STRING)
232
- rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
233
-
234
- xmlNodeAddContent(xnode, (xmlChar*)StringValuePtr(str));
235
- }
236
- return(self);
237
- }
238
-
239
- /*
240
- * call-seq:
241
- * node.child_add(node)
242
- *
243
- * Set a child node for this node.
244
- */
245
- static VALUE
246
- rxml_node_child_add(VALUE self, VALUE rnode) {
247
- return rxml_node_child_set_aux(self, rnode);
248
- }
249
-
250
- /*
251
- * call-seq:
252
- * node.doc -> document
253
- *
254
- * Obtain the XML::Document this node belongs to.
255
- */
256
- static VALUE
257
- rxml_node_doc(VALUE self) {
258
- xmlNodePtr xnode;
259
- xmlDocPtr doc=NULL;
260
-
261
- Data_Get_Struct(self, xmlNode, xnode);
262
-
263
- switch (xnode->type) {
264
- case XML_DOCUMENT_NODE:
265
- #ifdef LIBXML_DOCB_ENABLED
266
- case XML_DOCB_DOCUMENT_NODE:
267
- #endif
268
- case XML_HTML_DOCUMENT_NODE:
269
- doc = NULL;
270
- break;
271
- case XML_ATTRIBUTE_NODE:
272
- {
273
- xmlAttrPtr attr = (xmlAttrPtr) xnode;
274
- doc = attr->doc;
275
- break;
276
- }
277
- case XML_NAMESPACE_DECL:
278
- doc = NULL;
279
- break;
280
- default:
281
- doc = xnode->doc;
282
- break;
283
- }
284
-
285
- if (doc == NULL)
286
- return(Qnil);
287
-
288
- if ( doc->_private == NULL )
289
- rb_raise(rb_eRuntimeError,"existing document object has no ruby-instance");
290
-
291
- return (VALUE)doc->_private;
292
- }
293
-
294
-
295
- /*
296
- * call-seq:
297
- * node.dump -> (true|nil)
298
- *
299
- * Dump this node to stdout.
300
- */
301
- static VALUE
302
- rxml_node_dump(VALUE self) {
303
- xmlNodePtr xnode;
304
- xmlBufferPtr buf;
305
-
306
- Data_Get_Struct(self, xmlNode, xnode);
307
-
308
- if (xnode->doc == NULL)
309
- return(Qnil);
310
-
311
- buf = xmlBufferCreate();
312
- xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
313
- xmlBufferDump(stdout, buf);
314
- xmlBufferFree(buf);
315
- return(Qtrue);
316
- }
317
-
318
-
319
- /*
320
- * call-seq:
321
- * node.debug_dump -> (true|nil)
322
- *
323
- * Dump this node to stdout, including any debugging
324
- * information.
325
- */
326
- static VALUE
327
- rxml_node_debug_dump(VALUE self) {
328
- xmlNodePtr xnode;
329
- Data_Get_Struct(self, xmlNode, xnode);
330
-
331
- if (xnode->doc == NULL)
332
- return(Qnil);
333
-
334
- xmlElemDump(stdout, xnode->doc, xnode);
335
- return(Qtrue);
336
- }
337
-
338
- /*
339
- * call-seq:
340
- * node.each -> XML::Node
341
- *
342
- * Iterates over this node's children, including text
343
- * nodes, element nodes, etc. If you wish to iterate
344
- * only over child elements, use XML::Node#each_element.
345
- *
346
- * doc = XML::Document.new('model/books.xml')
347
- * doc.root.each {|node| puts node}
348
- */
349
- static VALUE
350
- rxml_node_each(VALUE self) {
351
- xmlNodePtr xnode;
352
- xmlNodePtr xchild;
353
- Data_Get_Struct(self, xmlNode, xnode);
354
-
355
- xchild = xnode->children;
356
-
357
- while (xchild) {
358
- rb_yield(rxml_node2_wrap(cXMLNode, xchild));
359
- xchild = xchild->next;
360
- }
361
- return Qnil;
362
- }
363
-
364
-
365
- /*
366
- * call-seq:
367
- * node.empty? -> (true|false)
368
- *
369
- * Determine whether this node is empty.
370
- */
371
- static VALUE
372
- rxml_node_empty_q(VALUE self) {
373
- xmlNodePtr xnode;
374
- Data_Get_Struct(self, xmlNode, xnode);
375
- if (xnode == NULL)
376
- return(Qnil);
377
-
378
- return((xmlIsBlankNode(xnode) == 1) ? Qtrue : Qfalse);
379
- }
380
-
381
-
382
- static VALUE rxml_node_to_s(VALUE self);
383
-
384
- /*
385
- * call-seq:
386
- * node.eql?(other_node) => (true|false)
387
- *
388
- * Test equality between the two nodes. Two nodes are equal
389
- * if they are the same node or have the same XML representation.*/
390
- static VALUE
391
- rxml_node_eql_q(VALUE self, VALUE other) {
392
- if (self == other)
393
- {
394
- return Qtrue;
395
- }
396
- else if NIL_P(other)
397
- {
398
- return Qfalse;
399
- }
400
- else
401
- {
402
- VALUE self_xml;
403
- VALUE other_xml;
404
-
405
- if (rb_obj_is_kind_of(other, cXMLNode) == Qfalse)
406
- rb_raise(rb_eTypeError, "Nodes can only be compared against other nodes");
407
-
408
- self_xml = rxml_node_to_s(self);
409
- other_xml = rxml_node_to_s(other);
410
- return(rb_funcall(self_xml, rb_intern("=="), 1, other_xml));
411
- }
412
- }
413
-
414
- /*
415
- * call-seq:
416
- * XML::Node.new_cdata(content = nil) -> XML::Node
417
- *
418
- * Create a new #CDATA node, optionally setting
419
- * the node's content.
420
- */
421
- static VALUE
422
- rxml_node_new_cdata(int argc, VALUE *argv, VALUE class) {
423
- xmlNodePtr xnode;
424
- VALUE str=Qnil;
425
-
426
- switch(argc) {
427
- case 1:
428
- str = argv[0];
429
- Check_Type(str, T_STRING);
430
- if (!NIL_P(str)) {
431
- xnode = xmlNewCDataBlock(NULL, (xmlChar*)StringValuePtr(str), xmlStrlen((xmlChar*)StringValuePtr(str)));
432
- } else {
433
- xnode = xmlNewCDataBlock(NULL, NULL , 0);
434
- }
435
-
436
- if (xnode == NULL)
437
- return(Qnil);
438
-
439
- return rxml_node2_wrap(class,xnode);
440
-
441
- default:
442
- rb_raise(rb_eArgError, "wrong number of arguments (1)");
443
- }
444
-
445
- // not reached
446
- return(Qnil);
447
- }
448
-
449
-
450
- /*
451
- * call-seq:
452
- * XML::Node.new_comment(content = nil) -> XML::Node
453
- *
454
- * Create a new comment node, optionally setting
455
- * the node's content.
456
- *
457
- */
458
- static VALUE
459
- rxml_node_new_comment(int argc, VALUE *argv, VALUE class) {
460
- xmlNodePtr xnode;
461
- VALUE str=Qnil;
462
-
463
- switch(argc) {
464
- case 1:
465
- str = argv[0];
466
- Check_Type(str, T_STRING);
467
- // TODO xmlNewComment wrongly? adds \n before and after the comment
468
- if (!NIL_P(str)) {
469
- xnode = xmlNewComment((xmlChar*)StringValuePtr(str));
470
- } else {
471
- xnode = xmlNewComment(NULL);
472
- }
473
-
474
- if (xnode == NULL)
475
- return(Qnil);
476
-
477
- return rxml_node2_wrap(class,xnode);
478
-
479
- default:
480
- rb_raise(rb_eArgError, "wrong number of arguments (1)");
481
- }
482
-
483
- // not reached
484
- return(Qnil);
485
- }
486
-
487
-
488
- /*
489
- * call-seq:
490
- * node.lang -> "string"
491
- *
492
- * Obtain the language set for this node, if any.
493
- * This is set in XML via the xml:lang attribute.
494
- */
495
- static VALUE
496
- rxml_node_lang_get(VALUE self) {
497
- xmlNodePtr xnode;
498
- xmlChar *lang;
499
- VALUE result = Qnil;
500
-
501
- Data_Get_Struct(self, xmlNode, xnode);
502
- lang = xmlNodeGetLang(xnode);
503
-
504
- if (lang) {
505
- result = rb_str_new2((const char*)lang);
506
- xmlFree(lang);
507
- }
508
-
509
- return(result);
510
- }
511
-
512
-
513
- // TODO node_lang_set should support setting back to nil
514
-
515
- /*
516
- * call-seq:
517
- * node.lang = "string"
518
- *
519
- * Set the language for this node. This affects the value
520
- * of the xml:lang attribute.
521
- */
522
- static VALUE
523
- rxml_node_lang_set(VALUE self, VALUE lang) {
524
- xmlNodePtr xnode;
525
-
526
- Check_Type(lang, T_STRING);
527
- Data_Get_Struct(self, xmlNode, xnode);
528
- xmlNodeSetLang(xnode, (xmlChar*)StringValuePtr(lang));
529
-
530
- return(Qtrue);
531
- }
532
-
533
-
534
- /*
535
- * call-seq:
536
- * node.last -> XML::Node
537
- *
538
- * Obtain the last child node of this node, if any.
539
- */
540
- static VALUE
541
- rxml_node_last_get(VALUE self) {
542
- xmlNodePtr xnode;
543
-
544
- Data_Get_Struct(self, xmlNode, xnode);
545
-
546
- if (xnode->last)
547
- return(rxml_node2_wrap(cXMLNode, xnode->last));
548
- else
549
- return(Qnil);
550
- }
551
-
552
- /*
553
- * call-seq:
554
- * node.line_num -> num
555
- *
556
- * Obtain the line number (in the XML document) that this
557
- * node was read from. If +default_line_numbers+ is set
558
- * false (the default), this method returns zero.
559
- */
560
- static VALUE
561
- rxml_node_line_num(VALUE self) {
562
- xmlNodePtr xnode;
563
- long line_num;
564
- Data_Get_Struct(self, xmlNode, xnode);
565
-
566
- if (!xmlLineNumbersDefaultValue)
567
- rb_warn("Line numbers were not retained: use XML::Parser::default_line_numbers=true");
568
-
569
- line_num = xmlGetLineNo(xnode);
570
- if (line_num == -1)
571
- return(Qnil);
572
- else
573
- return(INT2NUM((long)line_num));
574
- }
575
-
576
-
577
- /*
578
- * call-seq:
579
- * node.xlink? -> (true|false)
580
- *
581
- * Determine whether this node is an xlink node.
582
- */
583
- static VALUE
584
- rxml_node_xlink_q(VALUE self) {
585
- xmlNodePtr xnode;
586
- xlinkType xlt;
587
-
588
- Data_Get_Struct(self, xmlNode, xnode);
589
- xlt = xlinkIsLink(xnode->doc, xnode);
590
-
591
- if (xlt == XLINK_TYPE_NONE)
592
- return(Qfalse);
593
- else
594
- return(Qtrue);
595
- }
596
-
597
-
598
- /*
599
- * call-seq:
600
- * node.xlink_type -> num
601
- *
602
- * Obtain the type identifier for this xlink, if applicable.
603
- * If this is not an xlink node (see +xlink?+), will return
604
- * nil.
605
- */
606
- static VALUE
607
- rxml_node_xlink_type(VALUE self) {
608
- xmlNodePtr xnode;
609
- xlinkType xlt;
610
-
611
- Data_Get_Struct(self, xmlNode, xnode);
612
- xlt = xlinkIsLink(xnode->doc, xnode);
613
-
614
- if (xlt == XLINK_TYPE_NONE)
615
- return(Qnil);
616
- else
617
- return(INT2NUM(xlt));
618
- }
619
-
620
-
621
- /*
622
- * call-seq:
623
- * node.xlink_type_name -> "string"
624
- *
625
- * Obtain the type name for this xlink, if applicable.
626
- * If this is not an xlink node (see +xlink?+), will return
627
- * nil.
628
- */
629
- static VALUE
630
- rxml_node_xlink_type_name(VALUE self) {
631
- xmlNodePtr xnode;
632
- xlinkType xlt;
633
-
634
- Data_Get_Struct(self, xmlNode, xnode);
635
- xlt = xlinkIsLink(xnode->doc, xnode);
636
-
637
- switch(xlt) {
638
- case XLINK_TYPE_NONE:
639
- return(Qnil);
640
- case XLINK_TYPE_SIMPLE:
641
- return(rb_str_new2("simple"));
642
- case XLINK_TYPE_EXTENDED:
643
- return(rb_str_new2("extended"));
644
- case XLINK_TYPE_EXTENDED_SET:
645
- return(rb_str_new2("extended_set"));
646
- default:
647
- rb_fatal("Unknowng xlink type, %d", xlt);
648
- }
649
- }
650
-
651
- /*
652
- * call-seq:
653
- * node.name -> "string"
654
- *
655
- * Obtain this node's name.
656
- */
657
- static VALUE
658
- rxml_node_name_get(VALUE self) {
659
- xmlNodePtr xnode;
660
- const xmlChar *name;
661
-
662
- Data_Get_Struct(self, xmlNode, xnode);
663
-
664
- switch (xnode->type) {
665
- case XML_DOCUMENT_NODE:
666
- #ifdef LIBXML_DOCB_ENABLED
667
- case XML_DOCB_DOCUMENT_NODE:
668
- #endif
669
- case XML_HTML_DOCUMENT_NODE:
670
- {
671
- xmlDocPtr doc = (xmlDocPtr) xnode;
672
- name = doc->URL;
673
- break;
674
- }
675
- case XML_ATTRIBUTE_NODE:
676
- {
677
- xmlAttrPtr attr = (xmlAttrPtr) xnode;
678
- name = attr->name;
679
- break;
680
- }
681
- case XML_NAMESPACE_DECL:
682
- {
683
- xmlNsPtr ns = (xmlNsPtr) xnode;
684
- name = ns->prefix;
685
- break;
686
- }
687
- default:
688
- name = xnode->name;
689
- break;
690
- }
691
-
692
- if (xnode->name == NULL)
693
- return(Qnil);
694
- else
695
- return(rb_str_new2((const char*)name));
696
- }
697
-
698
-
699
- /*
700
- * call-seq:
701
- * node.name = "string"
702
- *
703
- * Set this node's name.
704
- */
705
- static VALUE
706
- rxml_node_name_set(VALUE self, VALUE name) {
707
- xmlNodePtr xnode;
708
-
709
- Check_Type(name, T_STRING);
710
- Data_Get_Struct(self, xmlNode, xnode);
711
- xmlNodeSetName(xnode, (xmlChar*)StringValuePtr(name));
712
- return(Qtrue);
713
- }
714
-
715
-
716
- /*
717
- * call-seq:
718
- * node.namespace -> [namespace, ..., namespace]
719
- *
720
- * Obtain an array of +XML::NS+ objects representing
721
- * this node's xmlns attributes
722
- */
723
- static VALUE
724
- rxml_node_namespace_get(VALUE self) {
725
- xmlNodePtr xnode;
726
- xmlNsPtr *nsList, *cur;
727
- VALUE arr, ns;
728
-
729
- Data_Get_Struct(self, xmlNode, xnode);
730
- if (xnode == NULL)
731
- return(Qnil);
732
-
733
- nsList = xmlGetNsList(xnode->doc, xnode);
734
-
735
- if (nsList == NULL)
736
- return(Qnil);
737
-
738
- arr = rb_ary_new();
739
- for (cur = nsList; *cur != NULL; cur++) {
740
- ns = rxml_ns_wrap(*cur);
741
- if (ns == Qnil)
742
- continue;
743
- else
744
- rb_ary_push(arr, ns);
745
- }
746
- xmlFree(nsList);
747
-
748
- return(arr);
749
- }
750
-
751
-
752
- /*
753
- * call-seq:
754
- * node.namespace_node -> namespace.
755
- *
756
- * Obtain this node's namespace node.
757
- */
758
- static VALUE
759
- rxml_node_namespace_get_node(VALUE self) {
760
- xmlNodePtr xnode;
761
-
762
- Data_Get_Struct(self, xmlNode, xnode);
763
- if (xnode->ns == NULL)
764
- return(Qnil);
765
- else
766
- return rxml_ns_wrap(xnode->ns);
767
- }
768
-
769
- // TODO namespace_set can take varargs (in fact, must if used
770
- // with strings), but I cannot see how you can call
771
- // that version, apart from with 'send'
772
- //
773
- // Would sure be nice to support foo.namespace['foo'] = 'bar'
774
- // but maybe that's not practical...
775
-
776
- /*
777
- * call-seq:
778
- * node.namespace = namespace
779
- *
780
- * Add the specified XML::NS object to this node's xmlns attributes.
781
- */
782
- static VALUE
783
- rxml_node_namespace_set(int argc, VALUE *argv, VALUE self) {
784
- VALUE rns, rprefix;
785
- xmlNodePtr xnode;
786
- xmlNsPtr xns;
787
- char *cp, *href;
788
-
789
- Data_Get_Struct(self, xmlNode, xnode);
790
- switch (argc) {
791
- case 1:
792
- rns = argv[0];
793
- if (TYPE(rns) == T_STRING) {
794
- cp = strchr(StringValuePtr(rns), (int)':');
795
- if (cp == NULL) {
796
- rprefix = rns;
797
- href = NULL;
798
- } else {
799
- rprefix = rb_str_new(StringValuePtr(rns), (int)((long)cp - (long)StringValuePtr(rns)));
800
- href = &cp[1]; /* skip the : */
801
- }
802
- } else if (rb_obj_is_kind_of(rns, cXMLNS) == Qtrue) {
803
- Data_Get_Struct(self, xmlNs, xns);
804
- xmlSetNs(xnode, xns);
805
- return(rns);
806
- } else
807
- rb_raise(rb_eTypeError, "must pass a string or an XML::Ns object");
808
-
809
- /* Fall through to next case because when argc == 1, we need to
810
- * manually setup the additional args unless the arg passed is of
811
- * cXMLNS type */
812
- case 2:
813
- /* Don't want this code run in the fall through case */
814
- if (argc == 2) {
815
- rprefix = argv[0];
816
- href = StringValuePtr(argv[1]);
817
- }
818
-
819
- xns = xmlNewNs(xnode, (xmlChar*)href, (xmlChar*)StringValuePtr(rprefix));
820
- if (xns == NULL)
821
- rxml_raise(&xmlLastError);
822
- else
823
- return rxml_ns_wrap(xns);
824
- break;
825
-
826
- default:
827
- rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
828
- }
829
-
830
- /* can't get here */
831
- return(Qnil);
832
- }
833
-
834
-
835
- /*
836
- * memory2 implementation: xmlNode->_private holds a reference
837
- * to the wrapping ruby object VALUE when there is one.
838
- * traversal for marking is upward, and top levels are marked
839
- * through and lower level mark entry.
840
- *
841
- * All ruby retrieval for an xml
842
- * node will result in the same ruby instance. When all handles to them
843
- * go out of scope, then ruby_xfree gets called and _private is set to NULL.
844
- * If the xmlNode has no parent or document, then call xmlFree.
845
- */
846
- void
847
- rxml_node2_free(xmlNodePtr xnode) {
848
-
849
- if (xnode != NULL) {
850
- xnode->_private=NULL;
851
-
852
- if (xnode->doc==NULL && xnode->parent==NULL) {
853
- xmlFreeNode(xnode);
854
- }
855
- }
856
- }
857
-
858
- void
859
- rxml_node_mark_common(xmlNodePtr xnode) {
860
- if (xnode->parent == NULL ) {
861
- #ifdef NODE_DEBUG
862
- fprintf(stderr,"mark no parent r=0x%x *n=0x%x\n",rxn,node);
863
- #endif
864
- } else if (xnode->doc != NULL ) {
865
- if (xnode->doc->_private == NULL) {
866
- rb_bug("XmlNode Doc is not bound! (%s:%d)",
867
- __FILE__,__LINE__);
868
- }
869
- rb_gc_mark((VALUE)xnode->doc->_private);
870
- } else {
871
- while (xnode->parent != NULL )
872
- xnode = xnode->parent;
873
- if (xnode->_private == NULL )
874
- rb_warning("XmlNode Root Parent is not bound! (%s:%d)",
875
- __FILE__,__LINE__);
876
- else {
877
- rb_gc_mark((VALUE)xnode->_private);
878
- }
879
- }
880
- }
881
-
882
- void
883
- rxml_node2_mark(xmlNodePtr xnode) {
884
- if (xnode == NULL ) return;
885
-
886
- if (xnode->_private == NULL ) {
887
- rb_warning("XmlNode is not bound! (%s:%d)",
888
- __FILE__,__LINE__);
889
- return;
890
- }
891
-
892
- rxml_node_mark_common(xnode);
893
- }
894
-
895
- VALUE
896
- rxml_node2_wrap(VALUE class, xmlNodePtr xnode)
897
- {
898
- VALUE obj;
899
-
900
- // This node is already wrapped
901
- if (xnode->_private != NULL) {
902
- return (VALUE)xnode->_private;
903
- }
904
-
905
- obj=Data_Wrap_Struct(class,
906
- rxml_node2_mark, rxml_node2_free,
907
- xnode);
908
-
909
- xnode->_private=(void*)obj;
910
- return obj;
911
- }
912
-
913
- /*
914
- * call-seq:
915
- * XML::Node.new_string(namespace, name, content) -> XML::Node
916
- *
917
- * Create a new element node in the specified namespace with the
918
- * supplied name and content.
919
- */
920
- static VALUE
921
- rxml_node_new_string(VALUE klass, VALUE ns, VALUE name, VALUE val)
922
- {
923
- xmlNodePtr xnode;
924
- xmlNsPtr xns = NULL;
925
- VALUE node;
926
-
927
- if (!NIL_P(ns)) {
928
- Data_Get_Struct(ns, xmlNs, xns);
929
- }
930
-
931
- xnode = xmlNewNode(xns,(xmlChar*)StringValuePtr(name));
932
- xnode->_private=NULL;
933
-
934
- node = rxml_node2_wrap(klass, xnode);
935
- rb_obj_call_init(node, 0, NULL);
936
-
937
- if (!NIL_P(val))
938
- {
939
- if (TYPE(val) != T_STRING)
940
- val = rb_obj_as_string(val);
941
-
942
- rxml_node_content_set(node, val);
943
- }
944
- return node;
945
- }
946
-
947
- /*
948
- * call-seq:
949
- * XML::Node.new(name, content = nil) -> XML::Node
950
- * XML::Node.new_element(name, content = nil) -> XML::Node
951
- *
952
- * Create a new element node with the specified name, optionally setting
953
- * the node's content.
954
- * backward compatibility for <.5 new
955
- */
956
- static VALUE
957
- rxml_node_new_string_bc(int argc, VALUE *argv, VALUE class)
958
- {
959
- VALUE content=Qnil;
960
- VALUE name=Qnil;
961
- switch(argc) {
962
- case 2:
963
- content=argv[1];
964
- if ( TYPE(content) != T_STRING)
965
- content=rb_obj_as_string(content);
966
-
967
- case 1:
968
- name=check_string_or_symbol( argv[0] );
969
- return rxml_node_new_string(class,Qnil,name,content);
970
-
971
- default:
972
- rb_raise(rb_eArgError, "wrong number of arguments (1 or 2) given %d",argc);
973
- }
974
- }
975
-
976
- /*
977
- * call-seq:
978
- * node.next -> XML::Node
979
- *
980
- * Obtain the next sibling node, if any.
981
- */
982
- static VALUE
983
- rxml_node_next_get(VALUE self) {
984
- xmlNodePtr xnode;
985
-
986
- Data_Get_Struct(self, xmlNode, xnode);
987
-
988
- if (xnode->next)
989
- return(rxml_node2_wrap(cXMLNode, xnode->next));
990
- else
991
- return(Qnil);
992
- }
993
-
994
-
995
- /*
996
- * call-seq:
997
- * node.next = node
998
- *
999
- * Insert the specified node as this node's next sibling.
1000
- */
1001
- static VALUE
1002
- rxml_node_next_set(VALUE self, VALUE rnode) {
1003
- xmlNodePtr cnode, pnode, ret;
1004
-
1005
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1006
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1007
-
1008
- Data_Get_Struct(self, xmlNode, pnode);
1009
- Data_Get_Struct(rnode, xmlNode, cnode);
1010
-
1011
- ret = xmlAddNextSibling(pnode, cnode);
1012
- if (ret == NULL)
1013
- rxml_raise(&xmlLastError);
1014
-
1015
- return(rxml_node2_wrap(cXMLNode, ret));
1016
- }
1017
-
1018
-
1019
- /*
1020
- * call-seq:
1021
- * node.ns? -> (true|false)
1022
- *
1023
- * Determine whether this node has a namespace.
1024
- */
1025
- static VALUE
1026
- rxml_node_ns_q(VALUE self) {
1027
- xmlNodePtr xnode;
1028
- Data_Get_Struct(self, xmlNode, xnode);
1029
- if (xnode->ns == NULL)
1030
- return(Qfalse);
1031
- else
1032
- return(Qtrue);
1033
- }
1034
-
1035
- /*
1036
- * call-seq:
1037
- * node.ns_def? -> (true|false)
1038
- *
1039
- * Obtain an array of +XML::NS+ objects representing
1040
- * this node's xmlns attributes
1041
- */
1042
- static VALUE
1043
- rxml_node_ns_def_q(VALUE self) {
1044
- xmlNodePtr xnode;
1045
- Data_Get_Struct(self, xmlNode, xnode);
1046
- if (xnode->nsDef == NULL)
1047
- return(Qfalse);
1048
- else
1049
- return(Qtrue);
1050
- }
1051
-
1052
-
1053
- /*
1054
- * call-seq:
1055
- * node.ns_def -> namespace
1056
- *
1057
- * Obtain this node's default namespace.
1058
- */
1059
- static VALUE
1060
- rxml_node_ns_def_get(VALUE self) {
1061
- xmlNodePtr xnode;
1062
- Data_Get_Struct(self, xmlNode, xnode);
1063
- if (xnode->nsDef == NULL)
1064
- return(Qnil);
1065
- else
1066
- return(rxml_ns_wrap(xnode->nsDef));
1067
- }
1068
-
1069
-
1070
- /*
1071
- * call-seq:
1072
- * node.parent -> XML::Node
1073
- *
1074
- * Obtain this node's parent node, if any.
1075
- */
1076
- static VALUE
1077
- rxml_node_parent_get(VALUE self) {
1078
- xmlNodePtr xnode;
1079
-
1080
- Data_Get_Struct(self, xmlNode, xnode);
1081
-
1082
- if (xnode->parent)
1083
- return(rxml_node2_wrap(cXMLNode, xnode->parent));
1084
- else
1085
- return(Qnil);
1086
- }
1087
-
1088
-
1089
- /*
1090
- * call-seq:
1091
- * node.path -> path
1092
- *
1093
- * Obtain this node's path.
1094
- */
1095
- static VALUE
1096
- rxml_node_path(VALUE self) {
1097
- xmlNodePtr xnode;
1098
- xmlChar *path;
1099
-
1100
- Data_Get_Struct(self, xmlNode, xnode);
1101
- path = xmlGetNodePath(xnode);
1102
-
1103
- if (path == NULL)
1104
- return(Qnil);
1105
- else
1106
- return(rb_str_new2((const char*)path));
1107
- }
1108
-
1109
-
1110
- /*
1111
- * call-seq:
1112
- * node.pointer -> XML::NodeSet
1113
- *
1114
- * Evaluates an XPointer expression relative to this node.
1115
- */
1116
- static VALUE
1117
- rxml_node_pointer(VALUE self, VALUE xptr_str) {
1118
- return(rxml_xpointer_point2(self, xptr_str));
1119
- }
1120
-
1121
-
1122
- /*
1123
- * call-seq:
1124
- * node.prev -> XML::Node
1125
- *
1126
- * Obtain the previous sibling, if any.
1127
- */
1128
- static VALUE
1129
- rxml_node_prev_get(VALUE self) {
1130
- xmlNodePtr xnode;
1131
- xmlNodePtr node;
1132
- Data_Get_Struct(self, xmlNode, xnode);
1133
-
1134
- switch (xnode->type) {
1135
- case XML_DOCUMENT_NODE:
1136
- #ifdef LIBXML_DOCB_ENABLED
1137
- case XML_DOCB_DOCUMENT_NODE:
1138
- #endif
1139
- case XML_HTML_DOCUMENT_NODE:
1140
- case XML_NAMESPACE_DECL:
1141
- node = NULL;
1142
- break;
1143
- case XML_ATTRIBUTE_NODE:
1144
- {
1145
- xmlAttrPtr attr = (xmlAttrPtr) xnode;
1146
- node = (xmlNodePtr) attr->prev;
1147
- }
1148
- break;
1149
- default:
1150
- node = xnode->prev;
1151
- break;
1152
- }
1153
-
1154
- if (node == NULL)
1155
- return(Qnil);
1156
- else
1157
- return(rxml_node2_wrap(cXMLNode, node));
1158
- }
1159
-
1160
-
1161
- /*
1162
- * call-seq:
1163
- * node.prev = node
1164
- *
1165
- * Insert the specified node as this node's previous sibling.
1166
- */
1167
- static VALUE
1168
- rxml_node_prev_set(VALUE self, VALUE rnode) {
1169
- xmlNodePtr cnode, pnode, ret;
1170
-
1171
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1172
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1173
-
1174
- Data_Get_Struct(self, xmlNode, pnode);
1175
- Data_Get_Struct(rnode, xmlNode, cnode);
1176
-
1177
- ret = xmlAddPrevSibling(pnode, cnode);
1178
- if (ret == NULL)
1179
- rxml_raise(&xmlLastError);
1180
-
1181
- return(rxml_node2_wrap(cXMLNode, ret));
1182
- }
1183
-
1184
- /*
1185
- * call-seq:
1186
- * node.attributes -> attributes
1187
- *
1188
- * Returns the XML::Attributes for this node.
1189
- */
1190
- static VALUE
1191
- rxml_node_attributes_get(VALUE self) {
1192
- xmlNodePtr xnode;
1193
-
1194
- Data_Get_Struct(self, xmlNode, xnode);
1195
- return rxml_attributes_new(xnode);
1196
- }
1197
-
1198
- /*
1199
- * call-seq:
1200
- * node.property("name") -> "string"
1201
- * node["name"] -> "string"
1202
- *
1203
- * Obtain the named pyroperty.
1204
- */
1205
- static VALUE
1206
- rxml_node_attribute_get(VALUE self, VALUE name) {
1207
- VALUE attributes = rxml_node_attributes_get(self);
1208
- return rxml_attributes_attribute_get(attributes, name);
1209
- }
1210
-
1211
- /*
1212
- * call-seq:
1213
- * node["name"] = "string"
1214
- *
1215
- * Set the named property.
1216
- */
1217
- static VALUE
1218
- rxml_node_property_set(VALUE self, VALUE name, VALUE value) {
1219
- VALUE attributes = rxml_node_attributes_get(self);
1220
- return rxml_attributes_attribute_set(attributes, name, value);
1221
- }
1222
-
1223
-
1224
- /*
1225
- * call-seq:
1226
- * node.remove! -> nil
1227
- *
1228
- * Removes this node from it's parent.
1229
- */
1230
- static VALUE
1231
- rxml_node_remove_ex(VALUE self) {
1232
- xmlNodePtr xnode;
1233
- Data_Get_Struct(self, xmlNode, xnode);
1234
- xmlUnlinkNode(xnode);
1235
- return(Qnil);
1236
- }
1237
-
1238
-
1239
- /*
1240
- * call-seq:
1241
- * node.search_href -> namespace
1242
- *
1243
- * Search for a namespace by href.
1244
- */
1245
- static VALUE
1246
- rxml_node_search_href(VALUE self, VALUE href) {
1247
- xmlNodePtr xnode;
1248
-
1249
- Check_Type(href, T_STRING);
1250
- Data_Get_Struct(self, xmlNode, xnode);
1251
- return(rxml_ns_wrap(xmlSearchNsByHref(xnode->doc, xnode,
1252
- (xmlChar*)StringValuePtr(href))));
1253
- }
1254
-
1255
-
1256
- /*
1257
- * call-seq:
1258
- * node.search_ns -> namespace
1259
- *
1260
- * Search for a namespace by namespace.
1261
- */
1262
- static VALUE
1263
- rxml_node_search_ns(VALUE self, VALUE ns) {
1264
- xmlNodePtr xnode;
1265
-
1266
- Check_Type(ns, T_STRING);
1267
- Data_Get_Struct(self, xmlNode, xnode);
1268
- return(rxml_ns_wrap(xmlSearchNs(xnode->doc, xnode,
1269
- (xmlChar*)StringValuePtr(ns))));
1270
- }
1271
-
1272
-
1273
- /*
1274
- * call-seq:
1275
- * node.sibling(node) -> XML::Node
1276
- *
1277
- * Add the specified node as a sibling of this node.
1278
- */
1279
- static VALUE
1280
- rxml_node_sibling_set(VALUE self, VALUE rnode) {
1281
- xmlNodePtr cnode, pnode, ret;
1282
- VALUE obj;
1283
-
1284
- if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1285
- rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1286
-
1287
- Data_Get_Struct(self, xmlNode, pnode);
1288
- Data_Get_Struct(rnode, xmlNode, cnode);
1289
-
1290
- ret = xmlAddSibling(pnode, cnode);
1291
- if (ret == NULL)
1292
- rxml_raise(&xmlLastError);
1293
-
1294
- if (ret->_private==NULL)
1295
- obj=rxml_node2_wrap(cXMLNode,ret);
1296
- else
1297
- obj=(VALUE)ret->_private;
1298
-
1299
- return obj;
1300
- }
1301
-
1302
-
1303
- /*
1304
- * call-seq:
1305
- * node.space_preserve -> (true|false)
1306
- *
1307
- * Determine whether this node preserves whitespace.
1308
- */
1309
- static VALUE
1310
- rxml_node_space_preserve_get(VALUE self) {
1311
- xmlNodePtr xnode;
1312
-
1313
- Data_Get_Struct(self, xmlNode, xnode);
1314
- return(INT2NUM(xmlNodeGetSpacePreserve(xnode)));
1315
- }
1316
-
1317
-
1318
- /*
1319
- * call-seq:
1320
- * node.space_preserve = true|false
1321
- *
1322
- * Control whether this node preserves whitespace.
1323
- */
1324
- static VALUE
1325
- rxml_node_space_preserve_set(VALUE self, VALUE bool) {
1326
- xmlNodePtr xnode;
1327
- Data_Get_Struct(self, xmlNode, xnode);
1328
-
1329
- if (TYPE(bool) == T_FALSE)
1330
- xmlNodeSetSpacePreserve(xnode, 1);
1331
- else
1332
- xmlNodeSetSpacePreserve(xnode, 0);
1333
-
1334
- return(Qnil);
1335
- }
1336
-
1337
- /*
1338
- * call-seq:
1339
- * node.to_s -> "string"
1340
- *
1341
- * Coerce this node to a string representation of
1342
- * it's XML.
1343
- */
1344
- static VALUE
1345
- rxml_node_to_s(VALUE self) {
1346
- xmlNodePtr xnode;
1347
- xmlBufferPtr buf;
1348
- VALUE result;
1349
-
1350
- Data_Get_Struct(self, xmlNode, xnode);
1351
- buf = xmlBufferCreate();
1352
- xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
1353
- result = rb_str_new2((const char*)buf->content);
1354
-
1355
- xmlBufferFree(buf);
1356
- return result;
1357
- }
1358
-
1359
-
1360
- /*
1361
- * call-seq:
1362
- * node.type -> num
1363
- *
1364
- * Obtain this node's type identifier.
1365
- */
1366
- static VALUE
1367
- rxml_node_type(VALUE self) {
1368
- xmlNodePtr xnode;
1369
- Data_Get_Struct(self, xmlNode, xnode);
1370
- return(INT2NUM(xnode->type));
1371
- }
1372
-
1373
-
1374
-
1375
-
1376
- /*
1377
- * call-seq:
1378
- * node.copy -> XML::Node
1379
- *
1380
- * Creates a copy of this node. To create a
1381
- * shallow copy set the deep parameter to false.
1382
- * To create a deep copy set the deep parameter
1383
- * to true.
1384
- *
1385
- */
1386
- static VALUE
1387
- rxml_node_copy(VALUE self, VALUE deep) {
1388
- xmlNodePtr xnode;
1389
- xmlNodePtr xcopy;
1390
- int recursive = (deep==Qnil || deep==Qfalse) ? 0 : 1;
1391
- Data_Get_Struct(self, xmlNode, xnode);
1392
-
1393
- xcopy = xmlCopyNode(xnode, recursive);
1394
-
1395
- if (xcopy)
1396
- return rxml_node2_wrap(cXMLNode, xcopy);
1397
- else
1398
- return Qnil;
1399
- }
1400
-
1401
- /*
1402
- * call-seq:
1403
- * XML::Node.new_text(content = nil) -> XML::Node
1404
- *
1405
- * Create a new text node, optionally setting
1406
- * the node's content.
1407
- *
1408
- */
1409
- static VALUE
1410
- rxml_node_new_text(VALUE class, VALUE text)
1411
- {
1412
- VALUE obj;
1413
- xmlNodePtr xnode;
1414
-
1415
- if ( NIL_P(text) )
1416
- return Qnil;
1417
-
1418
- if (TYPE(text) != T_STRING )
1419
- rb_raise(rb_eTypeError, "requires string argument");
1420
-
1421
- xnode=xmlNewText((xmlChar*)STR2CSTR(text));
1422
- if ( xnode == NULL )
1423
- return Qnil;
1424
-
1425
- obj=rxml_node2_wrap(class,xnode);
1426
- rb_obj_call_init(obj,0,NULL);
1427
- return obj;
1428
- }
1429
-
1430
- void
1431
- rxml_node_registerNode(xmlNodePtr node)
1432
- {
1433
- node->_private=NULL;
1434
- }
1435
-
1436
- void
1437
- rxml_node_deregisterNode(xmlNodePtr xnode)
1438
- {
1439
- VALUE node;
1440
-
1441
- if (xnode->_private==NULL ) return;
1442
- node = (VALUE)xnode->_private;
1443
- DATA_PTR(node) = NULL;
1444
- }
1445
-
1446
- // Rdoc needs to know
1447
- #ifdef RDOC_NEVER_DEFINED
1448
- mLibXML = rb_define_module("LibXML");
1449
- mXML = rb_define_module_under(mLibXML, "XML");
1450
- #endif
1451
-
1452
- void
1453
- ruby_init_xml_node(void) {
1454
- xmlRegisterNodeDefault(rxml_node_registerNode);
1455
- xmlDeregisterNodeDefault(rxml_node_deregisterNode);
1456
-
1457
- cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
1458
-
1459
- rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
1460
- rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
1461
- rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
1462
- rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
1463
- rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
1464
- rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
1465
- rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
1466
- rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
1467
- rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
1468
- rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
1469
- rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
1470
- rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
1471
- rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
1472
- rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
1473
-
1474
- rb_define_const(cXMLNode, "ELEMENT_NODE", INT2FIX(XML_ELEMENT_NODE));
1475
- rb_define_const(cXMLNode, "ATTRIBUTE_NODE", INT2FIX(XML_ATTRIBUTE_NODE));
1476
- rb_define_const(cXMLNode, "TEXT_NODE", INT2FIX(XML_TEXT_NODE));
1477
- rb_define_const(cXMLNode, "CDATA_SECTION_NODE", INT2FIX(XML_CDATA_SECTION_NODE));
1478
- rb_define_const(cXMLNode, "ENTITY_REF_NODE", INT2FIX(XML_ENTITY_REF_NODE));
1479
- rb_define_const(cXMLNode, "ENTITY_NODE", INT2FIX(XML_ENTITY_NODE));
1480
- rb_define_const(cXMLNode, "PI_NODE", INT2FIX(XML_PI_NODE));
1481
- rb_define_const(cXMLNode, "COMMENT_NODE", INT2FIX(XML_COMMENT_NODE));
1482
- rb_define_const(cXMLNode, "DOCUMENT_NODE", INT2FIX(XML_DOCUMENT_NODE));
1483
- rb_define_const(cXMLNode, "DOCUMENT_TYPE_NODE", INT2FIX(XML_DOCUMENT_TYPE_NODE));
1484
- rb_define_const(cXMLNode, "DOCUMENT_FRAG_NODE", INT2FIX(XML_DOCUMENT_FRAG_NODE));
1485
- rb_define_const(cXMLNode, "NOTATION_NODE", INT2FIX(XML_NOTATION_NODE));
1486
- rb_define_const(cXMLNode, "HTML_DOCUMENT_NODE", INT2FIX(XML_HTML_DOCUMENT_NODE));
1487
- rb_define_const(cXMLNode, "DTD_NODE", INT2FIX(XML_DTD_NODE));
1488
- rb_define_const(cXMLNode, "ELEMENT_DECL", INT2FIX(XML_ELEMENT_DECL));
1489
- rb_define_const(cXMLNode, "ATTRIBUTE_DECL", INT2FIX(XML_ATTRIBUTE_DECL));
1490
- rb_define_const(cXMLNode, "ENTITY_DECL", INT2FIX(XML_ENTITY_DECL));
1491
- rb_define_const(cXMLNode, "NAMESPACE_DECL", INT2FIX(XML_NAMESPACE_DECL));
1492
- rb_define_const(cXMLNode, "XINCLUDE_START", INT2FIX(XML_XINCLUDE_START));
1493
- rb_define_const(cXMLNode, "XINCLUDE_END", INT2FIX(XML_XINCLUDE_END));
1494
-
1495
- #ifdef LIBXML_DOCB_ENABLED
1496
- rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", INT2FIX(XML_DOCB_DOCUMENT_NODE));
1497
- #else
1498
- rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", Qnil);
1499
- #endif
1500
-
1501
- rb_define_singleton_method(cXMLNode, "new", rxml_node_new_string_bc, -1);
1502
- rb_define_singleton_method(cXMLNode, "new_cdata", rxml_node_new_cdata, -1);
1503
- rb_define_singleton_method(cXMLNode, "new_comment", rxml_node_new_comment, -1);
1504
- rb_define_singleton_method(cXMLNode, "new_text", rxml_node_new_text, 1);
1505
-
1506
- /* Traversal */
1507
- rb_include_module(cXMLNode, rb_mEnumerable);
1508
- rb_define_method(cXMLNode, "[]", rxml_node_attribute_get, 1);
1509
- rb_define_method(cXMLNode, "each", rxml_node_each, 0);
1510
- rb_define_method(cXMLNode, "first", rxml_node_first_get, 0);
1511
- rb_define_method(cXMLNode, "last", rxml_node_last_get, 0);
1512
- rb_define_method(cXMLNode, "next", rxml_node_next_get, 0);
1513
- rb_define_method(cXMLNode, "parent", rxml_node_parent_get, 0);
1514
- rb_define_method(cXMLNode, "prev", rxml_node_prev_get, 0);
1515
-
1516
- /* Modification */
1517
- rb_define_method(cXMLNode, "<<", rxml_node_content_add, 1);
1518
- rb_define_method(cXMLNode, "[]=", rxml_node_property_set, 2);
1519
- rb_define_method(cXMLNode, "child_add", rxml_node_child_add, 1);
1520
- rb_define_method(cXMLNode, "child=", rxml_node_child_set, 1);
1521
- rb_define_method(cXMLNode, "sibling=", rxml_node_sibling_set, 1);
1522
- rb_define_method(cXMLNode, "next=", rxml_node_next_set, 1);
1523
- rb_define_method(cXMLNode, "prev=", rxml_node_prev_set, 1);
1524
-
1525
-
1526
- /* Rest of the node api */
1527
- rb_define_method(cXMLNode, "attributes", rxml_node_attributes_get, 0);
1528
- rb_define_method(cXMLNode, "base", rxml_node_base_get, 0);
1529
- rb_define_method(cXMLNode, "base=", rxml_node_base_set, 1);
1530
- rb_define_method(cXMLNode, "blank?", rxml_node_empty_q, 0);
1531
- rb_define_method(cXMLNode, "copy", rxml_node_copy, 1);
1532
- rb_define_method(cXMLNode, "content", rxml_node_content_get, 0);
1533
- rb_define_method(cXMLNode, "content=", rxml_node_content_set, 1);
1534
- rb_define_method(cXMLNode, "content_stripped", rxml_node_content_stripped_get, 0);
1535
- rb_define_method(cXMLNode, "doc", rxml_node_doc, 0);
1536
- rb_define_method(cXMLNode, "dump", rxml_node_dump, 0);
1537
- rb_define_method(cXMLNode, "debug_dump", rxml_node_debug_dump, 0);
1538
- rb_define_method(cXMLNode, "empty?", rxml_node_empty_q, 0);
1539
- rb_define_method(cXMLNode, "eql?", rxml_node_eql_q, 1);
1540
- rb_define_method(cXMLNode, "lang", rxml_node_lang_get, 0);
1541
- rb_define_method(cXMLNode, "lang=", rxml_node_lang_set, 1);
1542
- rb_define_method(cXMLNode, "line_num", rxml_node_line_num, 0);
1543
- rb_define_method(cXMLNode, "name", rxml_node_name_get, 0);
1544
- rb_define_method(cXMLNode, "name=", rxml_node_name_set, 1);
1545
- rb_define_method(cXMLNode, "namespace", rxml_node_namespace_get, 0);
1546
- rb_define_method(cXMLNode, "namespace_node", rxml_node_namespace_get_node, 0);
1547
- rb_define_method(cXMLNode, "namespace=", rxml_node_namespace_set, -1);
1548
- rb_define_method(cXMLNode, "node_type", rxml_node_type, 0);
1549
- rb_define_method(cXMLNode, "ns", rxml_node_namespace_get, 0);
1550
- rb_define_method(cXMLNode, "ns?", rxml_node_ns_q, 0);
1551
- rb_define_method(cXMLNode, "ns_def?", rxml_node_ns_def_q, 0);
1552
- rb_define_method(cXMLNode, "ns_def", rxml_node_ns_def_get, 0);
1553
- rb_define_method(cXMLNode, "path", rxml_node_path, 0);
1554
- rb_define_method(cXMLNode, "pointer", rxml_node_pointer, 1);
1555
- rb_define_method(cXMLNode, "remove!", rxml_node_remove_ex, 0);
1556
- rb_define_method(cXMLNode, "search_ns", rxml_node_search_ns, 1);
1557
- rb_define_method(cXMLNode, "search_href", rxml_node_search_href, 1);
1558
- rb_define_method(cXMLNode, "space_preserve", rxml_node_space_preserve_get, 0);
1559
- rb_define_method(cXMLNode, "space_preserve=", rxml_node_space_preserve_set, 1);
1560
- rb_define_method(cXMLNode, "to_s", rxml_node_to_s, 0);
1561
- rb_define_method(cXMLNode, "xlink?", rxml_node_xlink_q, 0);
1562
- rb_define_method(cXMLNode, "xlink_type", rxml_node_xlink_type, 0);
1563
- rb_define_method(cXMLNode, "xlink_type_name", rxml_node_xlink_type_name, 0);
1564
-
1565
- rb_define_alias(cXMLNode, "==", "eql?");
1566
- }
1
+ /* $Id: ruby_xml_node.c 650 2008-11-30 03:40:22Z cfis $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "ruby_libxml.h"
6
+ #include "ruby_xml_node.h"
7
+
8
+ VALUE cXMLNode;
9
+
10
+ /* Document-class: LibXML::XML::Node
11
+ *
12
+ * Nodes are the primary objects that make up an XML document.
13
+ * The node class represents most node types that are found in
14
+ * an XML document (but not Attributes, see LibXML::XML::Attribute).
15
+ * It exposes libxml's full API for creating, querying
16
+ * moving and deleting node objects. Many of these methods are
17
+ * documented in the DOM Level 3 specification found at:
18
+ * http://www.w3.org/TR/DOM-Level-3-Core/. */
19
+
20
+ static VALUE rxml_node_content_set(VALUE self, VALUE content);
21
+
22
+ VALUE check_string_or_symbol(VALUE val)
23
+ {
24
+ if (TYPE(val) != T_STRING && TYPE(val) != T_SYMBOL)
25
+ {
26
+ rb_raise(rb_eTypeError,
27
+ "wrong argument type %s (expected String or Symbol)", rb_obj_classname(
28
+ val));
29
+ }
30
+ return rb_obj_as_string(val);
31
+ }
32
+
33
+ /*
34
+ * memory2 implementation: xmlNode->_private holds a reference
35
+ * to the wrapping ruby object VALUE when there is one.
36
+ * traversal for marking is upward, and top levels are marked
37
+ * through and lower level mark entry.
38
+ *
39
+ * All ruby retrieval for an xml
40
+ * node will result in the same ruby instance. When all handles to them
41
+ * go out of scope, then ruby_xfree gets called and _private is set to NULL.
42
+ * If the xmlNode has no parent or document, then call xmlFree.
43
+ */
44
+ void rxml_node2_free(xmlNodePtr xnode)
45
+ {
46
+ /* Set _private to NULL so that we won't reuse the
47
+ same, freed, Ruby wrapper object later.*/
48
+ xnode->_private = NULL;
49
+
50
+ if (xnode->doc == NULL && xnode->parent == NULL)
51
+ xmlFreeNode(xnode);
52
+ }
53
+
54
+ void rxml_node_mark_common(xmlNodePtr xnode)
55
+ {
56
+ if (xnode->parent == NULL)
57
+ return;
58
+
59
+ if (xnode->doc != NULL)
60
+ {
61
+ if (xnode->doc->_private == NULL)
62
+ rb_bug("XmlNode Doc is not bound! (%s:%d)", __FILE__,__LINE__);
63
+ rb_gc_mark((VALUE) xnode->doc->_private);
64
+ }
65
+ else
66
+ {
67
+ while (xnode->parent != NULL)
68
+ xnode = xnode->parent;
69
+
70
+ if (xnode->_private == NULL)
71
+ rb_warning("XmlNode Root Parent is not bound! (%s:%d)", __FILE__,__LINE__);
72
+ else
73
+ rb_gc_mark((VALUE) xnode->_private);
74
+ }
75
+ }
76
+
77
+ void rxml_node_mark(xmlNodePtr xnode)
78
+ {
79
+ if (xnode == NULL)
80
+ return;
81
+
82
+ if (xnode->_private == NULL)
83
+ {
84
+ rb_warning("XmlNode is not bound! (%s:%d)", __FILE__, __LINE__);
85
+ return;
86
+ }
87
+
88
+ rxml_node_mark_common(xnode);
89
+ }
90
+
91
+ VALUE rxml_node_wrap(VALUE class, xmlNodePtr xnode)
92
+ {
93
+ VALUE obj;
94
+
95
+ // This node is already wrapped
96
+ if (xnode->_private != NULL)
97
+ {
98
+ return (VALUE) xnode->_private;
99
+ }
100
+
101
+ obj = Data_Wrap_Struct(class, rxml_node_mark, rxml_node2_free, xnode);
102
+
103
+ xnode->_private = (void*) obj;
104
+ return obj;
105
+ }
106
+
107
+ static VALUE rxml_node_alloc(VALUE klass)
108
+ {
109
+ return Data_Wrap_Struct(klass, rxml_node_mark, rxml_node2_free, NULL);
110
+ }
111
+
112
+ /*
113
+ * call-seq:
114
+ * XML::Node.new_cdata(content = nil) -> XML::Node
115
+ *
116
+ * Create a new #CDATA node, optionally setting
117
+ * the node's content.
118
+ */
119
+ static VALUE rxml_node_new_cdata(int argc, VALUE *argv, VALUE klass)
120
+ {
121
+ VALUE content = Qnil;
122
+ xmlNodePtr xnode;
123
+
124
+ rb_scan_args(argc, argv, "01", &content);
125
+
126
+ if (NIL_P(content))
127
+ {
128
+ xnode = xmlNewCDataBlock(NULL, NULL, 0);
129
+ }
130
+ else
131
+ {
132
+ content = rb_obj_as_string(content);
133
+ xnode = xmlNewCDataBlock(NULL, (xmlChar*) StringValuePtr(content),
134
+ RSTRING_LEN(content));
135
+ }
136
+
137
+ if (xnode == NULL)
138
+ rxml_raise(&xmlLastError);
139
+
140
+ return rxml_node_wrap(klass, xnode);
141
+ }
142
+
143
+ /*
144
+ * call-seq:
145
+ * XML::Node.new_comment(content = nil) -> XML::Node
146
+ *
147
+ * Create a new comment node, optionally setting
148
+ * the node's content.
149
+ *
150
+ */
151
+ static VALUE rxml_node_new_comment(int argc, VALUE *argv, VALUE klass)
152
+ {
153
+ VALUE content = Qnil;
154
+ xmlNodePtr xnode;
155
+
156
+ rb_scan_args(argc, argv, "01", &content);
157
+
158
+ if (NIL_P(content))
159
+ {
160
+ xnode = xmlNewComment(NULL);
161
+ }
162
+ else
163
+ {
164
+ content = rb_obj_as_string(content);
165
+ xnode = xmlNewComment((xmlChar*) StringValueCStr(content));
166
+ }
167
+
168
+ if (xnode == NULL)
169
+ rxml_raise(&xmlLastError);
170
+
171
+ return rxml_node_wrap(klass, xnode);
172
+ }
173
+
174
+ /*
175
+ * call-seq:
176
+ * XML::Node.new_text(content) -> XML::Node
177
+ *
178
+ * Create a new text node.
179
+ *
180
+ */
181
+ static VALUE rxml_node_new_text(VALUE klass, VALUE content)
182
+ {
183
+ xmlNodePtr xnode;
184
+ Check_Type(content, T_STRING);
185
+ content = rb_obj_as_string(content);
186
+
187
+ xnode = xmlNewText((xmlChar*) StringValueCStr(content));
188
+
189
+ if (xnode == NULL)
190
+ rxml_raise(&xmlLastError);
191
+
192
+ return rxml_node_wrap(klass, xnode);
193
+ }
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 = check_string_or_symbol(name);
213
+
214
+ if (!NIL_P(ns))
215
+ Data_Get_Struct(ns, xmlNs, xns);
216
+
217
+ xnode = xmlNewNode(xns, (xmlChar*) StringValuePtr(name));
218
+ xnode->_private = (void*) self;
219
+ DATA_PTR( self) = xnode;
220
+
221
+ if (!NIL_P(content))
222
+ rxml_node_content_set(self, content);
223
+
224
+ return self;
225
+ }
226
+
227
+ /*
228
+ * call-seq:
229
+ * node.base -> "uri"
230
+ *
231
+ * Obtain this node's base URI.
232
+ */
233
+ static VALUE rxml_node_base_get(VALUE self)
234
+ {
235
+ xmlNodePtr xnode;
236
+ xmlChar* base_uri;
237
+ VALUE result = Qnil;
238
+
239
+ Data_Get_Struct(self, xmlNode, xnode);
240
+
241
+ if (xnode->doc == NULL)
242
+ return (result);
243
+
244
+ base_uri = xmlNodeGetBase(xnode->doc, xnode);
245
+ if (base_uri)
246
+ {
247
+ result = rb_str_new2((const char*) base_uri);
248
+ xmlFree(base_uri);
249
+ }
250
+
251
+ return (result);
252
+ }
253
+
254
+ // TODO node_base_set should support setting back to nil
255
+
256
+ /*
257
+ * call-seq:
258
+ * node.base = "uri"
259
+ *
260
+ * Set this node's base URI.
261
+ */
262
+ static VALUE rxml_node_base_set(VALUE self, VALUE uri)
263
+ {
264
+ xmlNodePtr xnode;
265
+
266
+ Check_Type(uri, T_STRING);
267
+ Data_Get_Struct(self, xmlNode, xnode);
268
+ if (xnode->doc == NULL)
269
+ return (Qnil);
270
+
271
+ xmlNodeSetBase(xnode, (xmlChar*) StringValuePtr(uri));
272
+ return (Qtrue);
273
+ }
274
+
275
+ /*
276
+ * call-seq:
277
+ * node.content -> "string"
278
+ *
279
+ * Obtain this node's content as a string.
280
+ */
281
+ static VALUE rxml_node_content_get(VALUE self)
282
+ {
283
+ xmlNodePtr xnode;
284
+ xmlChar *content;
285
+ VALUE result = Qnil;
286
+
287
+ Data_Get_Struct(self, xmlNode, xnode);
288
+ content = xmlNodeGetContent(xnode);
289
+ if (content)
290
+ {
291
+ result = rb_str_new2((const char *) content);
292
+ xmlFree(content);
293
+ }
294
+
295
+ return result;
296
+ }
297
+
298
+ /*
299
+ * call-seq:
300
+ * node.content = "string"
301
+ *
302
+ * Set this node's content to the specified string.
303
+ */
304
+ static VALUE rxml_node_content_set(VALUE self, VALUE content)
305
+ {
306
+ xmlNodePtr xnode;
307
+
308
+ Check_Type(content, T_STRING);
309
+ Data_Get_Struct(self, xmlNode, xnode);
310
+ // XXX docs indicate need for escaping entites, need to be done? danj
311
+ xmlNodeSetContent(xnode, (xmlChar*) StringValuePtr(content));
312
+ return (Qtrue);
313
+ }
314
+
315
+ /*
316
+ * call-seq:
317
+ * node.content_stripped -> "string"
318
+ *
319
+ * Obtain this node's stripped content.
320
+ *
321
+ * *Deprecated*: Stripped content can be obtained via the
322
+ * +content+ method.
323
+ */
324
+ static VALUE rxml_node_content_stripped_get(VALUE self)
325
+ {
326
+ xmlNodePtr xnode;
327
+ xmlChar* content;
328
+ VALUE result = Qnil;
329
+
330
+ Data_Get_Struct(self, xmlNode, xnode);
331
+
332
+ if (!xnode->content)
333
+ return result;
334
+
335
+ content = xmlNodeGetContent(xnode);
336
+ if (content)
337
+ {
338
+ result = rb_str_new2((const char*) content);
339
+ xmlFree(content);
340
+ }
341
+ return (result);
342
+ }
343
+
344
+ /*
345
+ * call-seq:
346
+ * node.first -> XML::Node
347
+ *
348
+ * Returns this node's first child node if any.
349
+ */
350
+ static VALUE rxml_node_first_get(VALUE self)
351
+ {
352
+ xmlNodePtr xnode;
353
+
354
+ Data_Get_Struct(self, xmlNode, xnode);
355
+
356
+ if (xnode->children)
357
+ return (rxml_node_wrap(cXMLNode, xnode->children));
358
+ else
359
+ return (Qnil);
360
+ }
361
+
362
+ /*
363
+ * underlying for child_set and child_add, difference being
364
+ * former raises on implicit copy, latter does not.
365
+ */
366
+ static VALUE rxml_node_child_set_aux(VALUE self, VALUE rnode)
367
+ {
368
+ xmlNodePtr pnode, chld, ret;
369
+
370
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
371
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
372
+
373
+ Data_Get_Struct(self, xmlNode, pnode);
374
+ Data_Get_Struct(rnode, xmlNode, chld);
375
+
376
+ if (chld->parent != NULL || chld->doc != NULL)
377
+ rb_raise(
378
+ rb_eRuntimeError,
379
+ "Cannot move a node from one document to another with child= or <<. First copy the node before moving it.");
380
+
381
+ ret = xmlAddChild(pnode, chld);
382
+ if (ret == NULL)
383
+ {
384
+ rxml_raise(&xmlLastError);
385
+ }
386
+ else if (ret == chld)
387
+ {
388
+ /* child was added whole to parent and we need to return it as a new object */
389
+ return rxml_node_wrap(cXMLNode, chld);
390
+ }
391
+ /* else */
392
+ /* If it was a text node, then ret should be parent->last, so we will just return ret. */
393
+ return rxml_node_wrap(cXMLNode, ret);
394
+ }
395
+
396
+ /*
397
+ * call-seq:
398
+ * node.child = node
399
+ *
400
+ * Set a child node for this node. Also called for <<
401
+ */
402
+ static VALUE rxml_node_child_set(VALUE self, VALUE rnode)
403
+ {
404
+ return rxml_node_child_set_aux(self, rnode);
405
+ }
406
+
407
+ /*
408
+ * call-seq:
409
+ * node << ("string" | node) -> XML::Node
410
+ *
411
+ * Add the specified string or XML::Node to this node's
412
+ * content. The returned node is the node that was
413
+ * added and not self, thereby allowing << calls to
414
+ * be chained.
415
+ */
416
+ static VALUE rxml_node_content_add(VALUE self, VALUE obj)
417
+ {
418
+ xmlNodePtr xnode;
419
+ VALUE str;
420
+
421
+ Data_Get_Struct(self, xmlNode, xnode);
422
+ /* XXX This should only be legal for a CDATA type node, I think,
423
+ * resulting in a merge of content, as if a string were passed
424
+ * danj 070827
425
+ */
426
+ if (rb_obj_is_kind_of(obj, cXMLNode))
427
+ {
428
+ rxml_node_child_set(self, obj);
429
+ }
430
+ else
431
+ {
432
+ str = rb_obj_as_string(obj);
433
+ if (NIL_P(str) || TYPE(str) != T_STRING)
434
+ rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
435
+
436
+ xmlNodeAddContent(xnode, (xmlChar*) StringValuePtr(str));
437
+ }
438
+ return (self);
439
+ }
440
+
441
+ /*
442
+ * call-seq:
443
+ * node.child_add(node)
444
+ *
445
+ * Set a child node for this node.
446
+ */
447
+ static VALUE rxml_node_child_add(VALUE self, VALUE rnode)
448
+ {
449
+ return rxml_node_child_set_aux(self, rnode);
450
+ }
451
+
452
+ /*
453
+ * call-seq:
454
+ * node.doc -> document
455
+ *
456
+ * Obtain the XML::Document this node belongs to.
457
+ */
458
+ static VALUE rxml_node_doc(VALUE self)
459
+ {
460
+ xmlNodePtr xnode;
461
+ xmlDocPtr doc = NULL;
462
+
463
+ Data_Get_Struct(self, xmlNode, xnode);
464
+
465
+ switch (xnode->type)
466
+ {
467
+ case XML_DOCUMENT_NODE:
468
+ #ifdef LIBXML_DOCB_ENABLED
469
+ case XML_DOCB_DOCUMENT_NODE:
470
+ #endif
471
+ case XML_HTML_DOCUMENT_NODE:
472
+ doc = NULL;
473
+ break;
474
+ case XML_ATTRIBUTE_NODE:
475
+ {
476
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
477
+ doc = attr->doc;
478
+ break;
479
+ }
480
+ case XML_NAMESPACE_DECL:
481
+ doc = NULL;
482
+ break;
483
+ default:
484
+ doc = xnode->doc;
485
+ break;
486
+ }
487
+
488
+ if (doc == NULL)
489
+ return (Qnil);
490
+
491
+ if (doc->_private == NULL)
492
+ rb_raise(rb_eRuntimeError, "existing document object has no ruby-instance");
493
+
494
+ return (VALUE) doc->_private;
495
+ }
496
+
497
+ /*
498
+ * call-seq:
499
+ * node.dump -> (true|nil)
500
+ *
501
+ * Dump this node to stdout.
502
+ */
503
+ static VALUE rxml_node_dump(VALUE self)
504
+ {
505
+ xmlNodePtr xnode;
506
+ xmlBufferPtr buf;
507
+
508
+ Data_Get_Struct(self, xmlNode, xnode);
509
+
510
+ if (xnode->doc == NULL)
511
+ return (Qnil);
512
+
513
+ buf = xmlBufferCreate();
514
+ xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
515
+ xmlBufferDump(stdout, buf);
516
+ xmlBufferFree(buf);
517
+ return (Qtrue);
518
+ }
519
+
520
+ /*
521
+ * call-seq:
522
+ * node.debug_dump -> (true|nil)
523
+ *
524
+ * Dump this node to stdout, including any debugging
525
+ * information.
526
+ */
527
+ static VALUE rxml_node_debug_dump(VALUE self)
528
+ {
529
+ xmlNodePtr xnode;
530
+ Data_Get_Struct(self, xmlNode, xnode);
531
+
532
+ if (xnode->doc == NULL)
533
+ return (Qnil);
534
+
535
+ xmlElemDump(stdout, xnode->doc, xnode);
536
+ return (Qtrue);
537
+ }
538
+
539
+ /*
540
+ * call-seq:
541
+ * node.each -> XML::Node
542
+ *
543
+ * Iterates over this node's children, including text
544
+ * nodes, element nodes, etc. If you wish to iterate
545
+ * only over child elements, use XML::Node#each_element.
546
+ *
547
+ * doc = XML::Document.new('model/books.xml')
548
+ * doc.root.each {|node| puts node}
549
+ */
550
+ static VALUE rxml_node_each(VALUE self)
551
+ {
552
+ xmlNodePtr xnode;
553
+ xmlNodePtr xchild;
554
+ Data_Get_Struct(self, xmlNode, xnode);
555
+
556
+ xchild = xnode->children;
557
+
558
+ while (xchild)
559
+ {
560
+ rb_yield(rxml_node_wrap(cXMLNode, xchild));
561
+ xchild = xchild->next;
562
+ }
563
+ return Qnil;
564
+ }
565
+
566
+ /*
567
+ * call-seq:
568
+ * node.empty? -> (true|false)
569
+ *
570
+ * Determine whether this node is empty.
571
+ */
572
+ static VALUE rxml_node_empty_q(VALUE self)
573
+ {
574
+ xmlNodePtr xnode;
575
+ Data_Get_Struct(self, xmlNode, xnode);
576
+ if (xnode == NULL)
577
+ return (Qnil);
578
+
579
+ return ((xmlIsBlankNode(xnode) == 1) ? Qtrue : Qfalse);
580
+ }
581
+
582
+ static VALUE rxml_node_to_s(VALUE self);
583
+
584
+ /*
585
+ * call-seq:
586
+ * node.eql?(other_node) => (true|false)
587
+ *
588
+ * Test equality between the two nodes. Two nodes are equal
589
+ * if they are the same node or have the same XML representation.*/
590
+ static VALUE rxml_node_eql_q(VALUE self, VALUE other)
591
+ {
592
+ if(self == other)
593
+ {
594
+ return Qtrue;
595
+ }
596
+ else if NIL_P(other)
597
+ {
598
+ return Qfalse;
599
+ }
600
+ else
601
+ {
602
+ VALUE self_xml;
603
+ VALUE other_xml;
604
+
605
+ if (rb_obj_is_kind_of(other, cXMLNode) == Qfalse)
606
+ rb_raise(rb_eTypeError, "Nodes can only be compared against other nodes");
607
+
608
+ self_xml = rxml_node_to_s(self);
609
+ other_xml = rxml_node_to_s(other);
610
+ return(rb_funcall(self_xml, rb_intern("=="), 1, other_xml));
611
+ }
612
+ }
613
+
614
+ /*
615
+ * call-seq:
616
+ * node.lang -> "string"
617
+ *
618
+ * Obtain the language set for this node, if any.
619
+ * This is set in XML via the xml:lang attribute.
620
+ */
621
+ static VALUE rxml_node_lang_get(VALUE self)
622
+ {
623
+ xmlNodePtr xnode;
624
+ xmlChar *lang;
625
+ VALUE result = Qnil;
626
+
627
+ Data_Get_Struct(self, xmlNode, xnode);
628
+ lang = xmlNodeGetLang(xnode);
629
+
630
+ if (lang)
631
+ {
632
+ result = rb_str_new2((const char*) lang);
633
+ xmlFree(lang);
634
+ }
635
+
636
+ return (result);
637
+ }
638
+
639
+ // TODO node_lang_set should support setting back to nil
640
+
641
+ /*
642
+ * call-seq:
643
+ * node.lang = "string"
644
+ *
645
+ * Set the language for this node. This affects the value
646
+ * of the xml:lang attribute.
647
+ */
648
+ static VALUE rxml_node_lang_set(VALUE self, VALUE lang)
649
+ {
650
+ xmlNodePtr xnode;
651
+
652
+ Check_Type(lang, T_STRING);
653
+ Data_Get_Struct(self, xmlNode, xnode);
654
+ xmlNodeSetLang(xnode, (xmlChar*) StringValuePtr(lang));
655
+
656
+ return (Qtrue);
657
+ }
658
+
659
+ /*
660
+ * call-seq:
661
+ * node.last -> XML::Node
662
+ *
663
+ * Obtain the last child node of this node, if any.
664
+ */
665
+ static VALUE rxml_node_last_get(VALUE self)
666
+ {
667
+ xmlNodePtr xnode;
668
+
669
+ Data_Get_Struct(self, xmlNode, xnode);
670
+
671
+ if (xnode->last)
672
+ return (rxml_node_wrap(cXMLNode, xnode->last));
673
+ else
674
+ return (Qnil);
675
+ }
676
+
677
+ /*
678
+ * call-seq:
679
+ * node.line_num -> num
680
+ *
681
+ * Obtain the line number (in the XML document) that this
682
+ * node was read from. If +default_line_numbers+ is set
683
+ * false (the default), this method returns zero.
684
+ */
685
+ static VALUE rxml_node_line_num(VALUE self)
686
+ {
687
+ xmlNodePtr xnode;
688
+ long line_num;
689
+ Data_Get_Struct(self, xmlNode, xnode);
690
+
691
+ if (!xmlLineNumbersDefaultValue)
692
+ rb_warn(
693
+ "Line numbers were not retained: use XML::Parser::default_line_numbers=true");
694
+
695
+ line_num = xmlGetLineNo(xnode);
696
+ if (line_num == -1)
697
+ return (Qnil);
698
+ else
699
+ return (INT2NUM((long) line_num));
700
+ }
701
+
702
+ /*
703
+ * call-seq:
704
+ * node.xlink? -> (true|false)
705
+ *
706
+ * Determine whether this node is an xlink node.
707
+ */
708
+ static VALUE rxml_node_xlink_q(VALUE self)
709
+ {
710
+ xmlNodePtr xnode;
711
+ xlinkType xlt;
712
+
713
+ Data_Get_Struct(self, xmlNode, xnode);
714
+ xlt = xlinkIsLink(xnode->doc, xnode);
715
+
716
+ if (xlt == XLINK_TYPE_NONE)
717
+ return (Qfalse);
718
+ else
719
+ return (Qtrue);
720
+ }
721
+
722
+ /*
723
+ * call-seq:
724
+ * node.xlink_type -> num
725
+ *
726
+ * Obtain the type identifier for this xlink, if applicable.
727
+ * If this is not an xlink node (see +xlink?+), will return
728
+ * nil.
729
+ */
730
+ static VALUE rxml_node_xlink_type(VALUE self)
731
+ {
732
+ xmlNodePtr xnode;
733
+ xlinkType xlt;
734
+
735
+ Data_Get_Struct(self, xmlNode, xnode);
736
+ xlt = xlinkIsLink(xnode->doc, xnode);
737
+
738
+ if (xlt == XLINK_TYPE_NONE)
739
+ return (Qnil);
740
+ else
741
+ return (INT2NUM(xlt));
742
+ }
743
+
744
+ /*
745
+ * call-seq:
746
+ * node.xlink_type_name -> "string"
747
+ *
748
+ * Obtain the type name for this xlink, if applicable.
749
+ * If this is not an xlink node (see +xlink?+), will return
750
+ * nil.
751
+ */
752
+ static VALUE rxml_node_xlink_type_name(VALUE self)
753
+ {
754
+ xmlNodePtr xnode;
755
+ xlinkType xlt;
756
+
757
+ Data_Get_Struct(self, xmlNode, xnode);
758
+ xlt = xlinkIsLink(xnode->doc, xnode);
759
+
760
+ switch (xlt)
761
+ {
762
+ case XLINK_TYPE_NONE:
763
+ return (Qnil);
764
+ case XLINK_TYPE_SIMPLE:
765
+ return (rb_str_new2("simple"));
766
+ case XLINK_TYPE_EXTENDED:
767
+ return (rb_str_new2("extended"));
768
+ case XLINK_TYPE_EXTENDED_SET:
769
+ return (rb_str_new2("extended_set"));
770
+ default:
771
+ rb_fatal("Unknowng xlink type, %d", xlt);
772
+ }
773
+ }
774
+
775
+ /*
776
+ * call-seq:
777
+ * node.name -> "string"
778
+ *
779
+ * Obtain this node's name.
780
+ */
781
+ static VALUE rxml_node_name_get(VALUE self)
782
+ {
783
+ xmlNodePtr xnode;
784
+ const xmlChar *name;
785
+
786
+ Data_Get_Struct(self, xmlNode, xnode);
787
+
788
+ switch (xnode->type)
789
+ {
790
+ case XML_DOCUMENT_NODE:
791
+ #ifdef LIBXML_DOCB_ENABLED
792
+ case XML_DOCB_DOCUMENT_NODE:
793
+ #endif
794
+ case XML_HTML_DOCUMENT_NODE:
795
+ {
796
+ xmlDocPtr doc = (xmlDocPtr) xnode;
797
+ name = doc->URL;
798
+ break;
799
+ }
800
+ case XML_ATTRIBUTE_NODE:
801
+ {
802
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
803
+ name = attr->name;
804
+ break;
805
+ }
806
+ case XML_NAMESPACE_DECL:
807
+ {
808
+ xmlNsPtr ns = (xmlNsPtr) xnode;
809
+ name = ns->prefix;
810
+ break;
811
+ }
812
+ default:
813
+ name = xnode->name;
814
+ break;
815
+ }
816
+
817
+ if (xnode->name == NULL)
818
+ return (Qnil);
819
+ else
820
+ return (rb_str_new2((const char*) name));
821
+ }
822
+
823
+ /*
824
+ * call-seq:
825
+ * node.name = "string"
826
+ *
827
+ * Set this node's name.
828
+ */
829
+ static VALUE rxml_node_name_set(VALUE self, VALUE name)
830
+ {
831
+ xmlNodePtr xnode;
832
+
833
+ Check_Type(name, T_STRING);
834
+ Data_Get_Struct(self, xmlNode, xnode);
835
+ xmlNodeSetName(xnode, (xmlChar*) StringValuePtr(name));
836
+ return (Qtrue);
837
+ }
838
+
839
+ /*
840
+ * call-seq:
841
+ * node.namespace -> [namespace, ..., namespace]
842
+ *
843
+ * Obtain an array of +XML::NS+ objects representing
844
+ * this node's xmlns attributes
845
+ */
846
+ static VALUE rxml_node_namespace_get(VALUE self)
847
+ {
848
+ xmlNodePtr xnode;
849
+ xmlNsPtr *nsList, *cur;
850
+ VALUE arr, ns;
851
+
852
+ Data_Get_Struct(self, xmlNode, xnode);
853
+ if (xnode == NULL)
854
+ return (Qnil);
855
+
856
+ nsList = xmlGetNsList(xnode->doc, xnode);
857
+
858
+ if (nsList == NULL)
859
+ return (Qnil);
860
+
861
+ arr = rb_ary_new();
862
+ for (cur = nsList; *cur != NULL; cur++)
863
+ {
864
+ ns = rxml_ns_wrap(*cur);
865
+ if (ns == Qnil)
866
+ continue;
867
+ else
868
+ rb_ary_push(arr, ns);
869
+ }
870
+ xmlFree(nsList);
871
+
872
+ return (arr);
873
+ }
874
+
875
+ /*
876
+ * call-seq:
877
+ * node.namespace_node -> namespace.
878
+ *
879
+ * Obtain this node's namespace node.
880
+ */
881
+ static VALUE rxml_node_namespace_get_node(VALUE self)
882
+ {
883
+ xmlNodePtr xnode;
884
+
885
+ Data_Get_Struct(self, xmlNode, xnode);
886
+ if (xnode->ns == NULL)
887
+ return (Qnil);
888
+ else
889
+ return rxml_ns_wrap(xnode->ns);
890
+ }
891
+
892
+ // TODO namespace_set can take varargs (in fact, must if used
893
+ // with strings), but I cannot see how you can call
894
+ // that version, apart from with 'send'
895
+ //
896
+ // Would sure be nice to support foo.namespace['foo'] = 'bar'
897
+ // but maybe that's not practical...
898
+
899
+ /*
900
+ * call-seq:
901
+ * node.namespace = namespace
902
+ *
903
+ * Add the specified XML::NS object to this node's xmlns attributes.
904
+ */
905
+ static VALUE rxml_node_namespace_set(int argc, VALUE *argv, VALUE self)
906
+ {
907
+ VALUE rns, rprefix;
908
+ xmlNodePtr xnode;
909
+ xmlNsPtr xns;
910
+ char *cp, *href;
911
+
912
+ Data_Get_Struct(self, xmlNode, xnode);
913
+ switch (argc)
914
+ {
915
+ case 1:
916
+ rns = argv[0];
917
+ if (TYPE(rns) == T_STRING)
918
+ {
919
+ cp = strchr(StringValuePtr(rns), (int) ':');
920
+ if (cp == NULL)
921
+ {
922
+ rprefix = rns;
923
+ href = NULL;
924
+ }
925
+ else
926
+ {
927
+ rprefix = rb_str_new(StringValuePtr(rns), (int) ((long) cp
928
+ - (long) StringValuePtr(rns)));
929
+ href = &cp[1]; /* skip the : */
930
+ }
931
+ }
932
+ else if (rb_obj_is_kind_of(rns, cXMLNS) == Qtrue)
933
+ {
934
+ Data_Get_Struct(self, xmlNs, xns);
935
+ xmlSetNs(xnode, xns);
936
+ return (rns);
937
+ }
938
+ else
939
+ rb_raise(rb_eTypeError, "must pass a string or an XML::Ns object");
940
+
941
+ /* Fall through to next case because when argc == 1, we need to
942
+ * manually setup the additional args unless the arg passed is of
943
+ * cXMLNS type */
944
+ case 2:
945
+ /* Don't want this code run in the fall through case */
946
+ if (argc == 2)
947
+ {
948
+ rprefix = argv[0];
949
+ href = StringValuePtr(argv[1]);
950
+ }
951
+
952
+ xns = xmlNewNs(xnode, (xmlChar*) href, (xmlChar*) StringValuePtr(rprefix));
953
+ if (xns == NULL)
954
+ rxml_raise(&xmlLastError);
955
+ else
956
+ return rxml_ns_wrap(xns);
957
+ break;
958
+
959
+ default:
960
+ rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
961
+ }
962
+
963
+ /* can't get here */
964
+ return (Qnil);
965
+ }
966
+
967
+ /*
968
+ * call-seq:
969
+ * node.next -> XML::Node
970
+ *
971
+ * Obtain the next sibling node, if any.
972
+ */
973
+ static VALUE rxml_node_next_get(VALUE self)
974
+ {
975
+ xmlNodePtr xnode;
976
+
977
+ Data_Get_Struct(self, xmlNode, xnode);
978
+
979
+ if (xnode->next)
980
+ return (rxml_node_wrap(cXMLNode, xnode->next));
981
+ else
982
+ return (Qnil);
983
+ }
984
+
985
+ /*
986
+ * call-seq:
987
+ * node.next = node
988
+ *
989
+ * Insert the specified node as this node's next sibling.
990
+ */
991
+ static VALUE rxml_node_next_set(VALUE self, VALUE rnode)
992
+ {
993
+ xmlNodePtr cnode, pnode, ret;
994
+
995
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
996
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
997
+
998
+ Data_Get_Struct(self, xmlNode, pnode);
999
+ Data_Get_Struct(rnode, xmlNode, cnode);
1000
+
1001
+ ret = xmlAddNextSibling(pnode, cnode);
1002
+ if (ret == NULL)
1003
+ rxml_raise(&xmlLastError);
1004
+
1005
+ return (rxml_node_wrap(cXMLNode, ret));
1006
+ }
1007
+
1008
+ /*
1009
+ * call-seq:
1010
+ * node.ns? -> (true|false)
1011
+ *
1012
+ * Determine whether this node has a namespace.
1013
+ */
1014
+ static VALUE rxml_node_ns_q(VALUE self)
1015
+ {
1016
+ xmlNodePtr xnode;
1017
+ Data_Get_Struct(self, xmlNode, xnode);
1018
+ if (xnode->ns == NULL)
1019
+ return (Qfalse);
1020
+ else
1021
+ return (Qtrue);
1022
+ }
1023
+
1024
+ /*
1025
+ * call-seq:
1026
+ * node.ns_def? -> (true|false)
1027
+ *
1028
+ * Obtain an array of +XML::NS+ objects representing
1029
+ * this node's xmlns attributes
1030
+ */
1031
+ static VALUE rxml_node_ns_def_q(VALUE self)
1032
+ {
1033
+ xmlNodePtr xnode;
1034
+ Data_Get_Struct(self, xmlNode, xnode);
1035
+ if (xnode->nsDef == NULL)
1036
+ return (Qfalse);
1037
+ else
1038
+ return (Qtrue);
1039
+ }
1040
+
1041
+ /*
1042
+ * call-seq:
1043
+ * node.ns_def -> namespace
1044
+ *
1045
+ * Obtain this node's default namespace.
1046
+ */
1047
+ static VALUE rxml_node_ns_def_get(VALUE self)
1048
+ {
1049
+ xmlNodePtr xnode;
1050
+ Data_Get_Struct(self, xmlNode, xnode);
1051
+ if (xnode->nsDef == NULL)
1052
+ return (Qnil);
1053
+ else
1054
+ return (rxml_ns_wrap(xnode->nsDef));
1055
+ }
1056
+
1057
+ /*
1058
+ * call-seq:
1059
+ * node.parent -> XML::Node
1060
+ *
1061
+ * Obtain this node's parent node, if any.
1062
+ */
1063
+ static VALUE rxml_node_parent_get(VALUE self)
1064
+ {
1065
+ xmlNodePtr xnode;
1066
+
1067
+ Data_Get_Struct(self, xmlNode, xnode);
1068
+
1069
+ if (xnode->parent)
1070
+ return (rxml_node_wrap(cXMLNode, xnode->parent));
1071
+ else
1072
+ return (Qnil);
1073
+ }
1074
+
1075
+ /*
1076
+ * call-seq:
1077
+ * node.path -> path
1078
+ *
1079
+ * Obtain this node's path.
1080
+ */
1081
+ static VALUE rxml_node_path(VALUE self)
1082
+ {
1083
+ xmlNodePtr xnode;
1084
+ xmlChar *path;
1085
+
1086
+ Data_Get_Struct(self, xmlNode, xnode);
1087
+ path = xmlGetNodePath(xnode);
1088
+
1089
+ if (path == NULL)
1090
+ return (Qnil);
1091
+ else
1092
+ return (rb_str_new2((const char*) path));
1093
+ }
1094
+
1095
+ /*
1096
+ * call-seq:
1097
+ * node.pointer -> XML::NodeSet
1098
+ *
1099
+ * Evaluates an XPointer expression relative to this node.
1100
+ */
1101
+ static VALUE rxml_node_pointer(VALUE self, VALUE xptr_str)
1102
+ {
1103
+ return (rxml_xpointer_point2(self, xptr_str));
1104
+ }
1105
+
1106
+ /*
1107
+ * call-seq:
1108
+ * node.prev -> XML::Node
1109
+ *
1110
+ * Obtain the previous sibling, if any.
1111
+ */
1112
+ static VALUE rxml_node_prev_get(VALUE self)
1113
+ {
1114
+ xmlNodePtr xnode;
1115
+ xmlNodePtr node;
1116
+ Data_Get_Struct(self, xmlNode, xnode);
1117
+
1118
+ switch (xnode->type)
1119
+ {
1120
+ case XML_DOCUMENT_NODE:
1121
+ #ifdef LIBXML_DOCB_ENABLED
1122
+ case XML_DOCB_DOCUMENT_NODE:
1123
+ #endif
1124
+ case XML_HTML_DOCUMENT_NODE:
1125
+ case XML_NAMESPACE_DECL:
1126
+ node = NULL;
1127
+ break;
1128
+ case XML_ATTRIBUTE_NODE:
1129
+ {
1130
+ xmlAttrPtr attr = (xmlAttrPtr) xnode;
1131
+ node = (xmlNodePtr) attr->prev;
1132
+ }
1133
+ break;
1134
+ default:
1135
+ node = xnode->prev;
1136
+ break;
1137
+ }
1138
+
1139
+ if (node == NULL)
1140
+ return (Qnil);
1141
+ else
1142
+ return (rxml_node_wrap(cXMLNode, node));
1143
+ }
1144
+
1145
+ /*
1146
+ * call-seq:
1147
+ * node.prev = node
1148
+ *
1149
+ * Insert the specified node as this node's previous sibling.
1150
+ */
1151
+ static VALUE rxml_node_prev_set(VALUE self, VALUE rnode)
1152
+ {
1153
+ xmlNodePtr cnode, pnode, ret;
1154
+
1155
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1156
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1157
+
1158
+ Data_Get_Struct(self, xmlNode, pnode);
1159
+ Data_Get_Struct(rnode, xmlNode, cnode);
1160
+
1161
+ ret = xmlAddPrevSibling(pnode, cnode);
1162
+ if (ret == NULL)
1163
+ rxml_raise(&xmlLastError);
1164
+
1165
+ return (rxml_node_wrap(cXMLNode, ret));
1166
+ }
1167
+
1168
+ /*
1169
+ * call-seq:
1170
+ * node.attributes -> attributes
1171
+ *
1172
+ * Returns the XML::Attributes for this node.
1173
+ */
1174
+ static VALUE rxml_node_attributes_get(VALUE self)
1175
+ {
1176
+ xmlNodePtr xnode;
1177
+
1178
+ Data_Get_Struct(self, xmlNode, xnode);
1179
+ return rxml_attributes_new(xnode);
1180
+ }
1181
+
1182
+ /*
1183
+ * call-seq:
1184
+ * node.property("name") -> "string"
1185
+ * node["name"] -> "string"
1186
+ *
1187
+ * Obtain the named pyroperty.
1188
+ */
1189
+ static VALUE rxml_node_attribute_get(VALUE self, VALUE name)
1190
+ {
1191
+ VALUE attributes = rxml_node_attributes_get(self);
1192
+ return rxml_attributes_attribute_get(attributes, name);
1193
+ }
1194
+
1195
+ /*
1196
+ * call-seq:
1197
+ * node["name"] = "string"
1198
+ *
1199
+ * Set the named property.
1200
+ */
1201
+ static VALUE rxml_node_property_set(VALUE self, VALUE name, VALUE value)
1202
+ {
1203
+ VALUE attributes = rxml_node_attributes_get(self);
1204
+ return rxml_attributes_attribute_set(attributes, name, value);
1205
+ }
1206
+
1207
+ /*
1208
+ * call-seq:
1209
+ * node.remove! -> node
1210
+ *
1211
+ * Removes this node and its children from its
1212
+ * document tree by setting its document,
1213
+ * parent and siblings to nil. You can add
1214
+ * the returned node back into a document.
1215
+ * Otherwise, the node will be freed once
1216
+ * any references to it go out of scope. */
1217
+
1218
+ static VALUE rxml_node_remove_ex(VALUE self)
1219
+ {
1220
+ xmlNodePtr xnode;
1221
+ Data_Get_Struct(self, xmlNode, xnode);
1222
+ /* Unlink the node from its parent. */
1223
+ xmlUnlinkNode(xnode);
1224
+ /* Now set the nodes parent to nil so it can
1225
+ be freed if the reference to it goes out of scope*/
1226
+ xmlSetTreeDoc(xnode, NULL);
1227
+
1228
+ /* Now return the removed node so the user can
1229
+ do something wiht it.*/
1230
+ return self;
1231
+ }
1232
+
1233
+ /*
1234
+ * call-seq:
1235
+ * node.search_href -> namespace
1236
+ *
1237
+ * Search for a namespace by href.
1238
+ */
1239
+ static VALUE rxml_node_search_href(VALUE self, VALUE href)
1240
+ {
1241
+ xmlNodePtr xnode;
1242
+
1243
+ Check_Type(href, T_STRING);
1244
+ Data_Get_Struct(self, xmlNode, xnode);
1245
+ return (rxml_ns_wrap(xmlSearchNsByHref(xnode->doc, xnode,
1246
+ (xmlChar*) StringValuePtr(href))));
1247
+ }
1248
+
1249
+ /*
1250
+ * call-seq:
1251
+ * node.search_ns -> namespace
1252
+ *
1253
+ * Search for a namespace by namespace.
1254
+ */
1255
+ static VALUE rxml_node_search_ns(VALUE self, VALUE ns)
1256
+ {
1257
+ xmlNodePtr xnode;
1258
+
1259
+ Check_Type(ns, T_STRING);
1260
+ Data_Get_Struct(self, xmlNode, xnode);
1261
+ return (rxml_ns_wrap(xmlSearchNs(xnode->doc, xnode,
1262
+ (xmlChar*) StringValuePtr(ns))));
1263
+ }
1264
+
1265
+ /*
1266
+ * call-seq:
1267
+ * node.sibling(node) -> XML::Node
1268
+ *
1269
+ * Add the specified node as a sibling of this node.
1270
+ */
1271
+ static VALUE rxml_node_sibling_set(VALUE self, VALUE rnode)
1272
+ {
1273
+ xmlNodePtr cnode, pnode, ret;
1274
+ VALUE obj;
1275
+
1276
+ if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
1277
+ rb_raise(rb_eTypeError, "Must pass an XML::Node object");
1278
+
1279
+ Data_Get_Struct(self, xmlNode, pnode);
1280
+ Data_Get_Struct(rnode, xmlNode, cnode);
1281
+
1282
+ ret = xmlAddSibling(pnode, cnode);
1283
+ if (ret == NULL)
1284
+ rxml_raise(&xmlLastError);
1285
+
1286
+ if (ret->_private == NULL)
1287
+ obj = rxml_node_wrap(cXMLNode, ret);
1288
+ else
1289
+ obj = (VALUE) ret->_private;
1290
+
1291
+ return obj;
1292
+ }
1293
+
1294
+ /*
1295
+ * call-seq:
1296
+ * node.space_preserve -> (true|false)
1297
+ *
1298
+ * Determine whether this node preserves whitespace.
1299
+ */
1300
+ static VALUE rxml_node_space_preserve_get(VALUE self)
1301
+ {
1302
+ xmlNodePtr xnode;
1303
+
1304
+ Data_Get_Struct(self, xmlNode, xnode);
1305
+ return (INT2NUM(xmlNodeGetSpacePreserve(xnode)));
1306
+ }
1307
+
1308
+ /*
1309
+ * call-seq:
1310
+ * node.space_preserve = true|false
1311
+ *
1312
+ * Control whether this node preserves whitespace.
1313
+ */
1314
+ static VALUE rxml_node_space_preserve_set(VALUE self, VALUE bool)
1315
+ {
1316
+ xmlNodePtr xnode;
1317
+ Data_Get_Struct(self, xmlNode, xnode);
1318
+
1319
+ if (TYPE(bool) == T_FALSE)
1320
+ xmlNodeSetSpacePreserve(xnode, 1);
1321
+ else
1322
+ xmlNodeSetSpacePreserve(xnode, 0);
1323
+
1324
+ return (Qnil);
1325
+ }
1326
+
1327
+ /*
1328
+ * call-seq:
1329
+ * node.to_s -> "string"
1330
+ *
1331
+ * Coerce this node to a string representation of
1332
+ * it's XML.
1333
+ */
1334
+ static VALUE rxml_node_to_s(VALUE self)
1335
+ {
1336
+ xmlNodePtr xnode;
1337
+ xmlBufferPtr buf;
1338
+ VALUE result;
1339
+
1340
+ Data_Get_Struct(self, xmlNode, xnode);
1341
+ buf = xmlBufferCreate();
1342
+ xmlNodeDump(buf, xnode->doc, xnode, 0, 1);
1343
+ result = rb_str_new2((const char*) buf->content);
1344
+
1345
+ xmlBufferFree(buf);
1346
+ return result;
1347
+ }
1348
+
1349
+ /*
1350
+ * call-seq:
1351
+ * node.type -> num
1352
+ *
1353
+ * Obtain this node's type identifier.
1354
+ */
1355
+ static VALUE rxml_node_type(VALUE self)
1356
+ {
1357
+ xmlNodePtr xnode;
1358
+ Data_Get_Struct(self, xmlNode, xnode);
1359
+ return (INT2NUM(xnode->type));
1360
+ }
1361
+
1362
+ /*
1363
+ * call-seq:
1364
+ * node.copy -> XML::Node
1365
+ *
1366
+ * Creates a copy of this node. To create a
1367
+ * shallow copy set the deep parameter to false.
1368
+ * To create a deep copy set the deep parameter
1369
+ * to true.
1370
+ *
1371
+ */
1372
+ static VALUE rxml_node_copy(VALUE self, VALUE deep)
1373
+ {
1374
+ xmlNodePtr xnode;
1375
+ xmlNodePtr xcopy;
1376
+ int recursive = (deep == Qnil || deep == Qfalse) ? 0 : 1;
1377
+ Data_Get_Struct(self, xmlNode, xnode);
1378
+
1379
+ xcopy = xmlCopyNode(xnode, recursive);
1380
+
1381
+ if (xcopy)
1382
+ return rxml_node_wrap(cXMLNode, xcopy);
1383
+ else
1384
+ return Qnil;
1385
+ }
1386
+
1387
+ void rxml_node_registerNode(xmlNodePtr node)
1388
+ {
1389
+ node->_private = NULL;
1390
+ }
1391
+
1392
+ void rxml_node_deregisterNode(xmlNodePtr xnode)
1393
+ {
1394
+ VALUE node;
1395
+
1396
+ if (xnode->_private == NULL)
1397
+ return;
1398
+ node = (VALUE) xnode->_private;
1399
+ DATA_PTR( node) = NULL;
1400
+ }
1401
+
1402
+ // Rdoc needs to know
1403
+ #ifdef RDOC_NEVER_DEFINED
1404
+ mLibXML = rb_define_module("LibXML");
1405
+ mXML = rb_define_module_under(mLibXML, "XML");
1406
+ #endif
1407
+
1408
+ void ruby_init_xml_node(void)
1409
+ {
1410
+ xmlRegisterNodeDefault(rxml_node_registerNode);
1411
+ xmlDeregisterNodeDefault(rxml_node_deregisterNode);
1412
+
1413
+ cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
1414
+
1415
+ rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
1416
+ rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
1417
+ rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
1418
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
1419
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
1420
+ rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
1421
+ rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
1422
+ rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
1423
+ rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
1424
+ rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
1425
+ rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
1426
+ rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
1427
+ rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
1428
+ rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
1429
+
1430
+ rb_define_const(cXMLNode, "ELEMENT_NODE", INT2FIX(XML_ELEMENT_NODE));
1431
+ rb_define_const(cXMLNode, "ATTRIBUTE_NODE", INT2FIX(XML_ATTRIBUTE_NODE));
1432
+ rb_define_const(cXMLNode, "TEXT_NODE", INT2FIX(XML_TEXT_NODE));
1433
+ rb_define_const(cXMLNode, "CDATA_SECTION_NODE", INT2FIX(
1434
+ XML_CDATA_SECTION_NODE));
1435
+ rb_define_const(cXMLNode, "ENTITY_REF_NODE", INT2FIX(XML_ENTITY_REF_NODE));
1436
+ rb_define_const(cXMLNode, "ENTITY_NODE", INT2FIX(XML_ENTITY_NODE));
1437
+ rb_define_const(cXMLNode, "PI_NODE", INT2FIX(XML_PI_NODE));
1438
+ rb_define_const(cXMLNode, "COMMENT_NODE", INT2FIX(XML_COMMENT_NODE));
1439
+ rb_define_const(cXMLNode, "DOCUMENT_NODE", INT2FIX(XML_DOCUMENT_NODE));
1440
+ rb_define_const(cXMLNode, "DOCUMENT_TYPE_NODE", INT2FIX(
1441
+ XML_DOCUMENT_TYPE_NODE));
1442
+ rb_define_const(cXMLNode, "DOCUMENT_FRAG_NODE", INT2FIX(
1443
+ XML_DOCUMENT_FRAG_NODE));
1444
+ rb_define_const(cXMLNode, "NOTATION_NODE", INT2FIX(XML_NOTATION_NODE));
1445
+ rb_define_const(cXMLNode, "HTML_DOCUMENT_NODE", INT2FIX(
1446
+ XML_HTML_DOCUMENT_NODE));
1447
+ rb_define_const(cXMLNode, "DTD_NODE", INT2FIX(XML_DTD_NODE));
1448
+ rb_define_const(cXMLNode, "ELEMENT_DECL", INT2FIX(XML_ELEMENT_DECL));
1449
+ rb_define_const(cXMLNode, "ATTRIBUTE_DECL", INT2FIX(XML_ATTRIBUTE_DECL));
1450
+ rb_define_const(cXMLNode, "ENTITY_DECL", INT2FIX(XML_ENTITY_DECL));
1451
+ rb_define_const(cXMLNode, "NAMESPACE_DECL", INT2FIX(XML_NAMESPACE_DECL));
1452
+ rb_define_const(cXMLNode, "XINCLUDE_START", INT2FIX(XML_XINCLUDE_START));
1453
+ rb_define_const(cXMLNode, "XINCLUDE_END", INT2FIX(XML_XINCLUDE_END));
1454
+
1455
+ #ifdef LIBXML_DOCB_ENABLED
1456
+ rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", INT2FIX(XML_DOCB_DOCUMENT_NODE));
1457
+ #else
1458
+ rb_define_const(cXMLNode, "DOCB_DOCUMENT_NODE", Qnil);
1459
+ #endif
1460
+
1461
+ rb_define_singleton_method(cXMLNode, "new_cdata", rxml_node_new_cdata, -1);
1462
+ rb_define_singleton_method(cXMLNode, "new_comment", rxml_node_new_comment, -1);
1463
+ rb_define_singleton_method(cXMLNode, "new_text", rxml_node_new_text, 1);
1464
+
1465
+ /* Initialization */
1466
+ rb_define_alloc_func(cXMLNode, rxml_node_alloc);
1467
+ rb_define_method(cXMLNode, "initialize", rxml_node_initialize, -1);
1468
+
1469
+ /* Traversal */
1470
+ rb_include_module(cXMLNode, rb_mEnumerable);
1471
+ rb_define_method(cXMLNode, "[]", rxml_node_attribute_get, 1);
1472
+ rb_define_method(cXMLNode, "each", rxml_node_each, 0);
1473
+ rb_define_method(cXMLNode, "first", rxml_node_first_get, 0);
1474
+ rb_define_method(cXMLNode, "last", rxml_node_last_get, 0);
1475
+ rb_define_method(cXMLNode, "next", rxml_node_next_get, 0);
1476
+ rb_define_method(cXMLNode, "parent", rxml_node_parent_get, 0);
1477
+ rb_define_method(cXMLNode, "prev", rxml_node_prev_get, 0);
1478
+
1479
+ /* Modification */
1480
+ rb_define_method(cXMLNode, "<<", rxml_node_content_add, 1);
1481
+ rb_define_method(cXMLNode, "[]=", rxml_node_property_set, 2);
1482
+ rb_define_method(cXMLNode, "child_add", rxml_node_child_add, 1);
1483
+ rb_define_method(cXMLNode, "child=", rxml_node_child_set, 1);
1484
+ rb_define_method(cXMLNode, "sibling=", rxml_node_sibling_set, 1);
1485
+ rb_define_method(cXMLNode, "next=", rxml_node_next_set, 1);
1486
+ rb_define_method(cXMLNode, "prev=", rxml_node_prev_set, 1);
1487
+
1488
+ /* Rest of the node api */
1489
+ rb_define_method(cXMLNode, "attributes", rxml_node_attributes_get, 0);
1490
+ rb_define_method(cXMLNode, "base", rxml_node_base_get, 0);
1491
+ rb_define_method(cXMLNode, "base=", rxml_node_base_set, 1);
1492
+ rb_define_method(cXMLNode, "blank?", rxml_node_empty_q, 0);
1493
+ rb_define_method(cXMLNode, "copy", rxml_node_copy, 1);
1494
+ rb_define_method(cXMLNode, "content", rxml_node_content_get, 0);
1495
+ rb_define_method(cXMLNode, "content=", rxml_node_content_set, 1);
1496
+ rb_define_method(cXMLNode, "content_stripped",
1497
+ rxml_node_content_stripped_get, 0);
1498
+ rb_define_method(cXMLNode, "doc", rxml_node_doc, 0);
1499
+ rb_define_method(cXMLNode, "dump", rxml_node_dump, 0);
1500
+ rb_define_method(cXMLNode, "debug_dump", rxml_node_debug_dump, 0);
1501
+ rb_define_method(cXMLNode, "empty?", rxml_node_empty_q, 0);
1502
+ rb_define_method(cXMLNode, "eql?", rxml_node_eql_q, 1);
1503
+ rb_define_method(cXMLNode, "lang", rxml_node_lang_get, 0);
1504
+ rb_define_method(cXMLNode, "lang=", rxml_node_lang_set, 1);
1505
+ rb_define_method(cXMLNode, "line_num", rxml_node_line_num, 0);
1506
+ rb_define_method(cXMLNode, "name", rxml_node_name_get, 0);
1507
+ rb_define_method(cXMLNode, "name=", rxml_node_name_set, 1);
1508
+ rb_define_method(cXMLNode, "namespace", rxml_node_namespace_get, 0);
1509
+ rb_define_method(cXMLNode, "namespace_node", rxml_node_namespace_get_node, 0);
1510
+ rb_define_method(cXMLNode, "namespace=", rxml_node_namespace_set, -1);
1511
+ rb_define_method(cXMLNode, "node_type", rxml_node_type, 0);
1512
+ rb_define_method(cXMLNode, "ns", rxml_node_namespace_get, 0);
1513
+ rb_define_method(cXMLNode, "ns?", rxml_node_ns_q, 0);
1514
+ rb_define_method(cXMLNode, "ns_def?", rxml_node_ns_def_q, 0);
1515
+ rb_define_method(cXMLNode, "ns_def", rxml_node_ns_def_get, 0);
1516
+ rb_define_method(cXMLNode, "path", rxml_node_path, 0);
1517
+ rb_define_method(cXMLNode, "pointer", rxml_node_pointer, 1);
1518
+ rb_define_method(cXMLNode, "remove!", rxml_node_remove_ex, 0);
1519
+ rb_define_method(cXMLNode, "search_ns", rxml_node_search_ns, 1);
1520
+ rb_define_method(cXMLNode, "search_href", rxml_node_search_href, 1);
1521
+ rb_define_method(cXMLNode, "space_preserve", rxml_node_space_preserve_get, 0);
1522
+ rb_define_method(cXMLNode, "space_preserve=", rxml_node_space_preserve_set, 1);
1523
+ rb_define_method(cXMLNode, "to_s", rxml_node_to_s, 0);
1524
+ rb_define_method(cXMLNode, "xlink?", rxml_node_xlink_q, 0);
1525
+ rb_define_method(cXMLNode, "xlink_type", rxml_node_xlink_type, 0);
1526
+ rb_define_method(cXMLNode, "xlink_type_name", rxml_node_xlink_type_name, 0);
1527
+
1528
+ rb_define_alias(cXMLNode, "==", "eql?");
1529
+ }