libxml-ruby 5.0.5 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY → CHANGELOG.md} +875 -923
  3. data/LICENSE +20 -20
  4. data/README.md +67 -0
  5. data/Rakefile +77 -98
  6. data/ext/libxml/extconf.rb +34 -20
  7. data/ext/libxml/libxml.c +67 -79
  8. data/ext/libxml/ruby_libxml.h +1 -1
  9. data/ext/libxml/ruby_xml_attr.c +338 -333
  10. data/ext/libxml/ruby_xml_attr.h +13 -12
  11. data/ext/libxml/ruby_xml_attr_decl.c +19 -12
  12. data/ext/libxml/ruby_xml_attr_decl.h +11 -11
  13. data/ext/libxml/ruby_xml_attributes.c +18 -9
  14. data/ext/libxml/ruby_xml_document.c +111 -98
  15. data/ext/libxml/ruby_xml_document.h +1 -0
  16. data/ext/libxml/ruby_xml_dtd.c +49 -19
  17. data/ext/libxml/ruby_xml_dtd.h +10 -9
  18. data/ext/libxml/ruby_xml_html_parser.c +91 -91
  19. data/ext/libxml/ruby_xml_html_parser.h +10 -10
  20. data/ext/libxml/ruby_xml_html_parser_context.c +19 -6
  21. data/ext/libxml/ruby_xml_html_parser_context.h +11 -10
  22. data/ext/libxml/ruby_xml_html_parser_options.c +48 -48
  23. data/ext/libxml/ruby_xml_html_parser_options.h +10 -10
  24. data/ext/libxml/ruby_xml_input_cbg.c +45 -17
  25. data/ext/libxml/ruby_xml_input_cbg.h +20 -20
  26. data/ext/libxml/ruby_xml_io.c +49 -47
  27. data/ext/libxml/ruby_xml_io.h +10 -10
  28. data/ext/libxml/ruby_xml_namespace.c +20 -12
  29. data/ext/libxml/ruby_xml_namespace.h +11 -10
  30. data/ext/libxml/ruby_xml_namespaces.c +313 -293
  31. data/ext/libxml/ruby_xml_namespaces.h +9 -9
  32. data/ext/libxml/ruby_xml_node.c +71 -32
  33. data/ext/libxml/ruby_xml_node.h +15 -13
  34. data/ext/libxml/ruby_xml_parser.c +91 -91
  35. data/ext/libxml/ruby_xml_parser_context.c +54 -47
  36. data/ext/libxml/ruby_xml_parser_context.h +11 -10
  37. data/ext/libxml/ruby_xml_reader.c +25 -15
  38. data/ext/libxml/ruby_xml_reader.h +14 -14
  39. data/ext/libxml/ruby_xml_registry.c +31 -0
  40. data/ext/libxml/ruby_xml_registry.h +22 -0
  41. data/ext/libxml/ruby_xml_relaxng.c +21 -5
  42. data/ext/libxml/ruby_xml_relaxng.h +9 -8
  43. data/ext/libxml/ruby_xml_sax2_handler.h +10 -10
  44. data/ext/libxml/ruby_xml_sax_parser.c +1 -1
  45. data/ext/libxml/ruby_xml_sax_parser.h +10 -10
  46. data/ext/libxml/ruby_xml_schema.c +18 -11
  47. data/ext/libxml/ruby_xml_schema.h +26 -25
  48. data/ext/libxml/ruby_xml_schema_attribute.c +7 -7
  49. data/ext/libxml/ruby_xml_schema_attribute.h +37 -37
  50. data/ext/libxml/ruby_xml_schema_element.c +8 -8
  51. data/ext/libxml/ruby_xml_schema_element.h +11 -11
  52. data/ext/libxml/ruby_xml_schema_facet.c +50 -50
  53. data/ext/libxml/ruby_xml_schema_facet.h +9 -9
  54. data/ext/libxml/ruby_xml_schema_type.c +12 -19
  55. data/ext/libxml/ruby_xml_schema_type.h +9 -9
  56. data/ext/libxml/ruby_xml_version.h +4 -4
  57. data/ext/libxml/ruby_xml_writer.c +1136 -1124
  58. data/ext/libxml/ruby_xml_writer.h +6 -6
  59. data/ext/libxml/ruby_xml_xinclude.c +20 -20
  60. data/ext/libxml/ruby_xml_xinclude.h +11 -11
  61. data/ext/libxml/ruby_xml_xpath.c +195 -195
  62. data/ext/libxml/ruby_xml_xpath.h +15 -15
  63. data/ext/libxml/ruby_xml_xpath_context.c +408 -362
  64. data/ext/libxml/ruby_xml_xpath_context.h +9 -9
  65. data/ext/libxml/ruby_xml_xpath_expression.c +11 -5
  66. data/ext/libxml/ruby_xml_xpath_expression.h +11 -10
  67. data/ext/libxml/ruby_xml_xpath_object.c +69 -54
  68. data/ext/libxml/ruby_xml_xpath_object.h +19 -17
  69. data/ext/vc/libxml_ruby/libxml_ruby.vcxproj +271 -0
  70. data/ext/xcode/libxml-ruby.xcodeproj/project.pbxproj +633 -0
  71. data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  72. data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  73. data/ext/xcode/libxml-ruby.xcodeproj/xcshareddata/xcschemes/libxml-ruby.xcscheme +80 -0
  74. data/lib/libxml/document.rb +0 -29
  75. data/lib/libxml/error.rb +30 -3
  76. data/lib/libxml/html_parser.rb +0 -16
  77. data/lib/libxml/node.rb +1 -3
  78. data/lib/libxml/parser.rb +0 -8
  79. data/lib/libxml/schema/attribute.rb +27 -19
  80. data/lib/libxml/schema/element.rb +20 -0
  81. data/lib/libxml/schema/type.rb +44 -21
  82. data/lib/libxml/schema.rb +47 -47
  83. data/lib/libxml-ruby.rb +30 -30
  84. data/libxml-ruby.gemspec +12 -16
  85. data/test/c14n/result/1-1-without-comments/example-1 +3 -3
  86. data/test/c14n/result/1-1-without-comments/example-2 +10 -10
  87. data/test/c14n/result/1-1-without-comments/example-3 +13 -13
  88. data/test/c14n/result/1-1-without-comments/example-4 +8 -8
  89. data/test/c14n/result/1-1-without-comments/example-5 +2 -2
  90. data/test/c14n/result/with-comments/example-1 +5 -5
  91. data/test/c14n/result/with-comments/example-2 +10 -10
  92. data/test/c14n/result/with-comments/example-3 +13 -13
  93. data/test/c14n/result/with-comments/example-4 +8 -8
  94. data/test/c14n/result/with-comments/example-5 +3 -3
  95. data/test/c14n/result/without-comments/example-1 +3 -3
  96. data/test/c14n/result/without-comments/example-2 +10 -10
  97. data/test/c14n/result/without-comments/example-3 +13 -13
  98. data/test/c14n/result/without-comments/example-4 +8 -8
  99. data/test/c14n/result/without-comments/example-5 +2 -2
  100. data/test/test_attr.rb +179 -180
  101. data/test/test_attr_decl.rb +131 -131
  102. data/test/test_attributes.rb +135 -135
  103. data/test/test_canonicalize.rb +122 -120
  104. data/test/test_document.rb +2 -4
  105. data/test/test_dtd.rb +12 -4
  106. data/test/test_encoding_sax.rb +114 -114
  107. data/test/test_error.rb +6 -3
  108. data/test/test_helper.rb +1 -0
  109. data/test/test_html_parser.rb +6 -2
  110. data/test/test_html_parser_context.rb +22 -22
  111. data/test/test_input_callbacks.rb +36 -0
  112. data/test/test_namespace.rb +1 -1
  113. data/test/test_namespaces.rb +200 -200
  114. data/test/test_node.rb +16 -0
  115. data/test/test_node_cdata.rb +50 -50
  116. data/test/test_node_comment.rb +32 -32
  117. data/test/test_node_copy.rb +40 -40
  118. data/test/test_node_edit.rb +176 -158
  119. data/test/test_node_pi.rb +37 -37
  120. data/test/test_node_text.rb +69 -69
  121. data/test/test_node_xlink.rb +28 -28
  122. data/test/test_parser.rb +5 -41
  123. data/test/test_parser_context.rb +198 -198
  124. data/test/test_properties.rb +38 -38
  125. data/test/test_reader.rb +55 -6
  126. data/test/test_relaxng.rb +59 -53
  127. data/test/test_sax_parser.rb +345 -345
  128. data/test/test_schema.rb +28 -0
  129. data/test/test_traversal.rb +152 -152
  130. data/test/test_writer.rb +469 -468
  131. data/test/test_xinclude.rb +20 -20
  132. data/test/test_xml.rb +3 -7
  133. data/test/test_xpath.rb +244 -244
  134. data/test/test_xpath_context.rb +87 -87
  135. data/test/test_xpath_expression.rb +37 -37
  136. metadata +33 -27
  137. data/README.rdoc +0 -208
  138. data/ext/libxml/extconf.h +0 -3
  139. data/ext/libxml/ruby_xml_cbg.c +0 -85
  140. data/lib/libxml/hpricot.rb +0 -78
  141. data/lib/libxml.rb +0 -5
  142. data/lib/xml/libxml.rb +0 -10
  143. data/lib/xml.rb +0 -14
  144. data/script/benchmark/depixelate +0 -634
  145. data/script/benchmark/hamlet.xml +0 -9055
  146. data/script/benchmark/parsecount +0 -170
  147. data/script/benchmark/sock_entries.xml +0 -507
  148. data/script/benchmark/throughput +0 -41
  149. data/script/test +0 -6
  150. data/test/test.rb +0 -5
  151. data/test/test_deprecated_require.rb +0 -12
@@ -1,333 +1,338 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- /*
4
- * Document-class: LibXML::XML::Attr
5
- *
6
- * Provides access to an attribute defined on an element.
7
- *
8
- * Basic Usage:
9
- *
10
- * require 'test_helper'
11
- *
12
- * doc = XML::Document.new(<some_file>)
13
- * attribute = doc.root.attributes.get_attribute_ns('http://www.w3.org/1999/xlink', 'href')
14
- * attribute.name == 'href'
15
- * attribute.value == 'http://www.mydocument.com'
16
- * attribute.remove!
17
- */
18
-
19
- /* Attributes are owned and freed by their nodes. Thus, its easier for the
20
- ruby bindings to not manage attribute memory management. This does mean
21
- that accessing a particular attribute multiple times will return multiple
22
- different ruby objects. Since we are not using free this works out fine.
23
- Previous versions of the bindings had a one to one mapping between ruby
24
- object and xml attribute, but that could result in segfaults because the
25
- ruby object could be gc'ed. In theory the mark method on the parent node
26
- could prevent that, but if an attribute is returned using an xpath statement
27
- then the node would never by surfaced to ruby and the mark method never
28
- called. */
29
-
30
- #include "ruby_libxml.h"
31
- #include "ruby_xml_attr.h"
32
-
33
- VALUE cXMLAttr;
34
-
35
- void rxml_attr_mark(xmlAttrPtr xattr)
36
- {
37
- /* This can happen if Ruby does a GC run after creating the
38
- new attribute but before initializing it. */
39
- if (xattr != NULL)
40
- rxml_node_mark((xmlNodePtr) xattr);
41
- }
42
-
43
- VALUE rxml_attr_wrap(xmlAttrPtr xattr)
44
- {
45
- return Data_Wrap_Struct(cXMLAttr, rxml_attr_mark, NULL, xattr);
46
- }
47
-
48
- static VALUE rxml_attr_alloc(VALUE klass)
49
- {
50
- return Data_Wrap_Struct(klass, rxml_attr_mark, NULL, NULL);
51
- }
52
-
53
- /*
54
- * call-seq:
55
- * attr.initialize(node, "name", "value")
56
- *
57
- * Creates a new attribute for the node.
58
- *
59
- * node: The XML::Node that will contain the attribute
60
- * name: The name of the attribute
61
- * value: The value of the attribute
62
- *
63
- * attr = XML::Attr.new(doc.root, 'name', 'libxml')
64
- */
65
- static VALUE rxml_attr_initialize(int argc, VALUE *argv, VALUE self)
66
- {
67
- VALUE node = argv[0];
68
- VALUE name = argv[1];
69
- VALUE value = argv[2];
70
- VALUE ns = (argc == 4 ? argv[3] : Qnil);
71
-
72
- xmlNodePtr xnode;
73
- xmlAttrPtr xattr;
74
-
75
- if (argc < 3 || argc > 4)
76
- rb_raise(rb_eArgError, "Wrong number of arguments (3 or 4)");
77
-
78
- Check_Type(name, T_STRING);
79
- Check_Type(value, T_STRING);
80
-
81
- Data_Get_Struct(node, xmlNode, xnode);
82
-
83
- if (xnode->type != XML_ELEMENT_NODE)
84
- rb_raise(rb_eArgError, "Attributes can only be created on element nodes.");
85
-
86
- if (NIL_P(ns))
87
- {
88
- xattr = xmlNewProp(xnode, (xmlChar*)StringValuePtr(name), (xmlChar*)StringValuePtr(value));
89
- }
90
- else
91
- {
92
- xmlNsPtr xns;
93
- Data_Get_Struct(ns, xmlNs, xns);
94
- xattr = xmlNewNsProp(xnode, xns, (xmlChar*)StringValuePtr(name), (xmlChar*)StringValuePtr(value));
95
- }
96
-
97
- if (!xattr)
98
- rb_raise(rb_eRuntimeError, "Could not create attribute.");
99
-
100
- DATA_PTR( self) = xattr;
101
- return self;
102
- }
103
-
104
- /*
105
- * call-seq:
106
- * attr.child -> node
107
- *
108
- * Obtain this attribute's child attribute(s).
109
- */
110
- static VALUE rxml_attr_child_get(VALUE self)
111
- {
112
- xmlAttrPtr xattr;
113
- Data_Get_Struct(self, xmlAttr, xattr);
114
- if (xattr->children == NULL)
115
- return Qnil;
116
- else
117
- return rxml_node_wrap((xmlNodePtr) xattr->children);
118
- }
119
-
120
-
121
- /*
122
- * call-seq:
123
- * attr.doc -> XML::Document
124
- *
125
- * Returns this attribute's document.
126
- *
127
- * doc.root.attributes.get_attribute('name').doc == doc
128
- */
129
- static VALUE rxml_attr_doc_get(VALUE self)
130
- {
131
- xmlAttrPtr xattr;
132
- Data_Get_Struct(self, xmlAttr, xattr);
133
- if (xattr->doc == NULL)
134
- return Qnil;
135
- else
136
- return rxml_document_wrap(xattr->doc);
137
- }
138
-
139
- /*
140
- * call-seq:
141
- * attr.last -> node
142
- *
143
- * Obtain the last attribute.
144
- */
145
- static VALUE rxml_attr_last_get(VALUE self)
146
- {
147
- xmlAttrPtr xattr;
148
- Data_Get_Struct(self, xmlAttr, xattr);
149
- if (xattr->last == NULL)
150
- return Qnil;
151
- else
152
- return rxml_node_wrap(xattr->last);
153
- }
154
-
155
- /*
156
- * call-seq:
157
- * attr.name -> "name"
158
- *
159
- * Obtain this attribute's name.
160
- */
161
- static VALUE rxml_attr_name_get(VALUE self)
162
- {
163
- xmlAttrPtr xattr;
164
- Data_Get_Struct(self, xmlAttr, xattr);
165
-
166
- if (xattr->name == NULL)
167
- return Qnil;
168
- else
169
- return rxml_new_cstr( xattr->name, NULL);
170
- }
171
-
172
- /*
173
- * call-seq:
174
- * attr.next -> node
175
- *
176
- * Obtain the next attribute.
177
- */
178
- static VALUE rxml_attr_next_get(VALUE self)
179
- {
180
- xmlAttrPtr xattr;
181
- Data_Get_Struct(self, xmlAttr, xattr);
182
- if (xattr->next == NULL)
183
- return Qnil;
184
- else
185
- return rxml_attr_wrap(xattr->next);
186
- }
187
-
188
- /*
189
- * call-seq:
190
- * attr.node_type -> num
191
- *
192
- * Obtain this node's type identifier.
193
- */
194
- static VALUE rxml_attr_node_type(VALUE self)
195
- {
196
- xmlAttrPtr xattr;
197
- Data_Get_Struct(self, xmlAttr, xattr);
198
- return INT2NUM(xattr->type);
199
- }
200
-
201
- /*
202
- * call-seq:
203
- * attr.ns -> namespace
204
- *
205
- * Obtain this attribute's associated XML::NS, if any.
206
- */
207
- static VALUE rxml_attr_ns_get(VALUE self)
208
- {
209
- xmlAttrPtr xattr;
210
- Data_Get_Struct(self, xmlAttr, xattr);
211
- if (xattr->ns == NULL)
212
- return Qnil;
213
- else
214
- return rxml_namespace_wrap(xattr->ns);
215
- }
216
-
217
- /*
218
- * call-seq:
219
- * attr.parent -> node
220
- *
221
- * Obtain this attribute node's parent.
222
- */
223
- static VALUE rxml_attr_parent_get(VALUE self)
224
- {
225
- xmlAttrPtr xattr;
226
- Data_Get_Struct(self, xmlAttr, xattr);
227
- if (xattr->parent == NULL)
228
- return Qnil;
229
- else
230
- return rxml_node_wrap(xattr->parent);
231
- }
232
-
233
- /*
234
- * call-seq:
235
- * attr.prev -> node
236
- *
237
- * Obtain the previous attribute.
238
- */
239
- static VALUE rxml_attr_prev_get(VALUE self)
240
- {
241
- xmlAttrPtr xattr;
242
- Data_Get_Struct(self, xmlAttr, xattr);
243
- if (xattr->prev == NULL)
244
- return Qnil;
245
- else
246
- return rxml_attr_wrap(xattr->prev);
247
- }
248
-
249
- /*
250
- * call-seq:
251
- * attr.remove! -> nil
252
- *
253
- * Removes this attribute from it's parent. Note
254
- * the attribute and its content is freed and can
255
- * no longer be used. If you try to use it you
256
- * will get a segmentation fault.
257
- */
258
- static VALUE rxml_attr_remove_ex(VALUE self)
259
- {
260
- xmlAttrPtr xattr;
261
- Data_Get_Struct(self, xmlAttr, xattr);
262
- xmlRemoveProp(xattr);
263
-
264
- RDATA(self)->data = NULL;
265
- RDATA(self)->dfree = NULL;
266
- RDATA(self)->dmark = NULL;
267
-
268
- return Qnil;
269
- }
270
-
271
- /*
272
- * call-seq:
273
- * attr.value -> "value"
274
- *
275
- * Obtain the value of this attribute.
276
- */
277
- VALUE rxml_attr_value_get(VALUE self)
278
- {
279
- xmlAttrPtr xattr;
280
- xmlChar *value;
281
- VALUE result = Qnil;
282
-
283
- Data_Get_Struct(self, xmlAttr, xattr);
284
- value = xmlNodeGetContent((xmlNodePtr)xattr);
285
-
286
- if (value != NULL)
287
- {
288
- result = rxml_new_cstr( value, NULL);
289
- xmlFree(value);
290
- }
291
- return result;
292
- }
293
-
294
- /*
295
- * call-seq:
296
- * attr.value = "value"
297
- *
298
- * Sets the value of this attribute.
299
- */
300
- VALUE rxml_attr_value_set(VALUE self, VALUE val)
301
- {
302
- xmlAttrPtr xattr;
303
-
304
- Check_Type(val, T_STRING);
305
- Data_Get_Struct(self, xmlAttr, xattr);
306
-
307
- if (xattr->ns)
308
- xmlSetNsProp(xattr->parent, xattr->ns, xattr->name,
309
- (xmlChar*) StringValuePtr(val));
310
- else
311
- xmlSetProp(xattr->parent, xattr->name, (xmlChar*) StringValuePtr(val));
312
-
313
- return (self);
314
- }
315
-
316
- void rxml_init_attr(void)
317
- {
318
- cXMLAttr = rb_define_class_under(mXML, "Attr", rb_cObject);
319
- rb_define_alloc_func(cXMLAttr, rxml_attr_alloc);
320
- rb_define_method(cXMLAttr, "initialize", rxml_attr_initialize, -1);
321
- rb_define_method(cXMLAttr, "child", rxml_attr_child_get, 0);
322
- rb_define_method(cXMLAttr, "doc", rxml_attr_doc_get, 0);
323
- rb_define_method(cXMLAttr, "last", rxml_attr_last_get, 0);
324
- rb_define_method(cXMLAttr, "name", rxml_attr_name_get, 0);
325
- rb_define_method(cXMLAttr, "next", rxml_attr_next_get, 0);
326
- rb_define_method(cXMLAttr, "node_type", rxml_attr_node_type, 0);
327
- rb_define_method(cXMLAttr, "ns", rxml_attr_ns_get, 0);
328
- rb_define_method(cXMLAttr, "parent", rxml_attr_parent_get, 0);
329
- rb_define_method(cXMLAttr, "prev", rxml_attr_prev_get, 0);
330
- rb_define_method(cXMLAttr, "remove!", rxml_attr_remove_ex, 0);
331
- rb_define_method(cXMLAttr, "value", rxml_attr_value_get, 0);
332
- rb_define_method(cXMLAttr, "value=", rxml_attr_value_set, 1);
333
- }
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ /*
4
+ * Document-class: LibXML::XML::Attr
5
+ *
6
+ * Provides access to an attribute defined on an element.
7
+ *
8
+ * Basic Usage:
9
+ *
10
+ * require 'test_helper'
11
+ *
12
+ * doc = XML::Document.new(<some_file>)
13
+ * attribute = doc.root.attributes.get_attribute_ns('http://www.w3.org/1999/xlink', 'href')
14
+ * attribute.name == 'href'
15
+ * attribute.value == 'http://www.mydocument.com'
16
+ * attribute.remove!
17
+ */
18
+
19
+ /* Attributes are owned and freed by their nodes. Thus, its easier for the
20
+ ruby bindings to not manage attribute memory management. This does mean
21
+ that accessing a particular attribute multiple times will return multiple
22
+ different ruby objects. Since we are not using free this works out fine.
23
+ Previous versions of the bindings had a one to one mapping between ruby
24
+ object and xml attribute, but that could result in segfaults because the
25
+ ruby object could be gc'ed. In theory the mark method on the parent node
26
+ could prevent that, but if an attribute is returned using an xpath statement
27
+ then the node would never by surfaced to ruby and the mark method never
28
+ called. */
29
+
30
+ #include "ruby_libxml.h"
31
+ #include "ruby_xml_attr.h"
32
+
33
+ VALUE cXMLAttr;
34
+
35
+ static void rxml_attr_mark(void *data)
36
+ {
37
+ xmlAttrPtr xattr = (xmlAttrPtr) data;
38
+ /* This can happen if Ruby does a GC run after creating the
39
+ new attribute but before initializing it. */
40
+ if (xattr != NULL)
41
+ rxml_node_mark((xmlNodePtr) xattr);
42
+ }
43
+
44
+ const rb_data_type_t rxml_attr_type = {
45
+ "LibXML::XML::Attr",
46
+ {rxml_attr_mark, NULL, 0},
47
+ &rxml_node_data_type, 0, RUBY_TYPED_FREE_IMMEDIATELY
48
+ };
49
+
50
+ VALUE rxml_attr_wrap(xmlAttrPtr xattr)
51
+ {
52
+ return TypedData_Wrap_Struct(cXMLAttr, &rxml_attr_type, xattr);
53
+ }
54
+
55
+ static VALUE rxml_attr_alloc(VALUE klass)
56
+ {
57
+ return TypedData_Wrap_Struct(klass, &rxml_attr_type, NULL);
58
+ }
59
+
60
+ /*
61
+ * call-seq:
62
+ * attr.initialize(node, "name", "value")
63
+ *
64
+ * Creates a new attribute for the node.
65
+ *
66
+ * node: The XML::Node that will contain the attribute
67
+ * name: The name of the attribute
68
+ * value: The value of the attribute
69
+ *
70
+ * attr = XML::Attr.new(doc.root, 'name', 'libxml')
71
+ */
72
+ static VALUE rxml_attr_initialize(int argc, VALUE *argv, VALUE self)
73
+ {
74
+ VALUE node = argv[0];
75
+ VALUE name = argv[1];
76
+ VALUE value = argv[2];
77
+ VALUE ns = (argc == 4 ? argv[3] : Qnil);
78
+
79
+ xmlNodePtr xnode;
80
+ xmlAttrPtr xattr;
81
+
82
+ if (argc < 3 || argc > 4)
83
+ rb_raise(rb_eArgError, "Wrong number of arguments (3 or 4)");
84
+
85
+ Check_Type(name, T_STRING);
86
+ Check_Type(value, T_STRING);
87
+
88
+ TypedData_Get_Struct(node, xmlNode, &rxml_node_data_type, xnode);
89
+
90
+ if (xnode->type != XML_ELEMENT_NODE)
91
+ rb_raise(rb_eArgError, "Attributes can only be created on element nodes.");
92
+
93
+ if (NIL_P(ns))
94
+ {
95
+ xattr = xmlNewProp(xnode, (xmlChar*)StringValuePtr(name), (xmlChar*)StringValuePtr(value));
96
+ }
97
+ else
98
+ {
99
+ xmlNsPtr xns;
100
+ TypedData_Get_Struct(ns, xmlNs, &rxml_namespace_type, xns);
101
+ xattr = xmlNewNsProp(xnode, xns, (xmlChar*)StringValuePtr(name), (xmlChar*)StringValuePtr(value));
102
+ }
103
+
104
+ if (!xattr)
105
+ rb_raise(rb_eRuntimeError, "Could not create attribute.");
106
+
107
+ RTYPEDDATA_DATA( self) = xattr;
108
+ return self;
109
+ }
110
+
111
+ /*
112
+ * call-seq:
113
+ * attr.child -> node
114
+ *
115
+ * Obtain this attribute's child attribute(s).
116
+ */
117
+ static VALUE rxml_attr_child_get(VALUE self)
118
+ {
119
+ xmlAttrPtr xattr;
120
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
121
+ if (xattr->children == NULL)
122
+ return Qnil;
123
+ else
124
+ return rxml_node_wrap((xmlNodePtr) xattr->children);
125
+ }
126
+
127
+
128
+ /*
129
+ * call-seq:
130
+ * attr.doc -> XML::Document
131
+ *
132
+ * Returns this attribute's document.
133
+ *
134
+ * doc.root.attributes.get_attribute('name').doc == doc
135
+ */
136
+ static VALUE rxml_attr_doc_get(VALUE self)
137
+ {
138
+ xmlAttrPtr xattr;
139
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
140
+ if (xattr->doc == NULL)
141
+ return Qnil;
142
+ else
143
+ return rxml_registry_lookup(xattr->doc);
144
+ }
145
+
146
+ /*
147
+ * call-seq:
148
+ * attr.last -> node
149
+ *
150
+ * Obtain the last attribute.
151
+ */
152
+ static VALUE rxml_attr_last_get(VALUE self)
153
+ {
154
+ xmlAttrPtr xattr;
155
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
156
+ if (xattr->last == NULL)
157
+ return Qnil;
158
+ else
159
+ return rxml_node_wrap(xattr->last);
160
+ }
161
+
162
+ /*
163
+ * call-seq:
164
+ * attr.name -> "name"
165
+ *
166
+ * Obtain this attribute's name.
167
+ */
168
+ static VALUE rxml_attr_name_get(VALUE self)
169
+ {
170
+ xmlAttrPtr xattr;
171
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
172
+
173
+ if (xattr->name == NULL)
174
+ return Qnil;
175
+ else
176
+ return rxml_new_cstr( xattr->name, NULL);
177
+ }
178
+
179
+ /*
180
+ * call-seq:
181
+ * attr.next -> node
182
+ *
183
+ * Obtain the next attribute.
184
+ */
185
+ static VALUE rxml_attr_next_get(VALUE self)
186
+ {
187
+ xmlAttrPtr xattr;
188
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
189
+ if (xattr->next == NULL)
190
+ return Qnil;
191
+ else
192
+ return rxml_attr_wrap(xattr->next);
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * attr.node_type -> num
198
+ *
199
+ * Obtain this node's type identifier.
200
+ */
201
+ static VALUE rxml_attr_node_type(VALUE self)
202
+ {
203
+ xmlAttrPtr xattr;
204
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
205
+ return INT2NUM(xattr->type);
206
+ }
207
+
208
+ /*
209
+ * call-seq:
210
+ * attr.ns -> namespace
211
+ *
212
+ * Obtain this attribute's associated XML::NS, if any.
213
+ */
214
+ static VALUE rxml_attr_ns_get(VALUE self)
215
+ {
216
+ xmlAttrPtr xattr;
217
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
218
+ if (xattr->ns == NULL)
219
+ return Qnil;
220
+ else
221
+ return rxml_namespace_wrap(xattr->ns);
222
+ }
223
+
224
+ /*
225
+ * call-seq:
226
+ * attr.parent -> node
227
+ *
228
+ * Obtain this attribute node's parent.
229
+ */
230
+ static VALUE rxml_attr_parent_get(VALUE self)
231
+ {
232
+ xmlAttrPtr xattr;
233
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
234
+ if (xattr->parent == NULL)
235
+ return Qnil;
236
+ else
237
+ return rxml_node_wrap(xattr->parent);
238
+ }
239
+
240
+ /*
241
+ * call-seq:
242
+ * attr.prev -> node
243
+ *
244
+ * Obtain the previous attribute.
245
+ */
246
+ static VALUE rxml_attr_prev_get(VALUE self)
247
+ {
248
+ xmlAttrPtr xattr;
249
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
250
+ if (xattr->prev == NULL)
251
+ return Qnil;
252
+ else
253
+ return rxml_attr_wrap(xattr->prev);
254
+ }
255
+
256
+ /*
257
+ * call-seq:
258
+ * attr.remove! -> nil
259
+ *
260
+ * Removes this attribute from it's parent. Note
261
+ * the attribute and its content is freed and can
262
+ * no longer be used. If you try to use it you
263
+ * will get a segmentation fault.
264
+ */
265
+ static VALUE rxml_attr_remove_ex(VALUE self)
266
+ {
267
+ xmlAttrPtr xattr;
268
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
269
+ xmlRemoveProp(xattr);
270
+
271
+ RTYPEDDATA_DATA(self) = NULL;
272
+
273
+ return Qnil;
274
+ }
275
+
276
+ /*
277
+ * call-seq:
278
+ * attr.value -> "value"
279
+ *
280
+ * Obtain the value of this attribute.
281
+ */
282
+ VALUE rxml_attr_value_get(VALUE self)
283
+ {
284
+ xmlAttrPtr xattr;
285
+ xmlChar *value;
286
+ VALUE result = Qnil;
287
+
288
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
289
+ value = xmlNodeGetContent((xmlNodePtr)xattr);
290
+
291
+ if (value != NULL)
292
+ {
293
+ result = rxml_new_cstr( value, NULL);
294
+ xmlFree(value);
295
+ }
296
+ return result;
297
+ }
298
+
299
+ /*
300
+ * call-seq:
301
+ * attr.value = "value"
302
+ *
303
+ * Sets the value of this attribute.
304
+ */
305
+ VALUE rxml_attr_value_set(VALUE self, VALUE val)
306
+ {
307
+ xmlAttrPtr xattr;
308
+
309
+ Check_Type(val, T_STRING);
310
+ TypedData_Get_Struct(self, xmlAttr, &rxml_attr_type, xattr);
311
+
312
+ if (xattr->ns)
313
+ xmlSetNsProp(xattr->parent, xattr->ns, xattr->name,
314
+ (xmlChar*) StringValuePtr(val));
315
+ else
316
+ xmlSetProp(xattr->parent, xattr->name, (xmlChar*) StringValuePtr(val));
317
+
318
+ return (self);
319
+ }
320
+
321
+ void rxml_init_attr(void)
322
+ {
323
+ cXMLAttr = rb_define_class_under(mXML, "Attr", rb_cObject);
324
+ rb_define_alloc_func(cXMLAttr, rxml_attr_alloc);
325
+ rb_define_method(cXMLAttr, "initialize", rxml_attr_initialize, -1);
326
+ rb_define_method(cXMLAttr, "child", rxml_attr_child_get, 0);
327
+ rb_define_method(cXMLAttr, "doc", rxml_attr_doc_get, 0);
328
+ rb_define_method(cXMLAttr, "last", rxml_attr_last_get, 0);
329
+ rb_define_method(cXMLAttr, "name", rxml_attr_name_get, 0);
330
+ rb_define_method(cXMLAttr, "next", rxml_attr_next_get, 0);
331
+ rb_define_method(cXMLAttr, "node_type", rxml_attr_node_type, 0);
332
+ rb_define_method(cXMLAttr, "ns", rxml_attr_ns_get, 0);
333
+ rb_define_method(cXMLAttr, "parent", rxml_attr_parent_get, 0);
334
+ rb_define_method(cXMLAttr, "prev", rxml_attr_prev_get, 0);
335
+ rb_define_method(cXMLAttr, "remove!", rxml_attr_remove_ex, 0);
336
+ rb_define_method(cXMLAttr, "value", rxml_attr_value_get, 0);
337
+ rb_define_method(cXMLAttr, "value=", rxml_attr_value_set, 1);
338
+ }