libxml-ruby 0.9.4-x86-mswin32-60 → 0.9.5-x86-mswin32-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) 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/mingw/libxml_ruby.dll.a +0 -0
  35. data/ext/mingw/libxml_ruby.so +0 -0
  36. data/ext/vc/libxml_ruby.vcproj +1 -1
  37. data/lib/libxml/error.rb +4 -4
  38. data/test/tc_node_edit.rb +14 -2
  39. data/test/tc_node_text.rb +9 -9
  40. 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
+ }