nokogiri 1.0.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (127) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +120 -0
  3. data/README.ja.txt +86 -0
  4. data/README.txt +87 -0
  5. data/Rakefile +264 -0
  6. data/ext/nokogiri/extconf.rb +59 -0
  7. data/ext/nokogiri/html_document.c +83 -0
  8. data/ext/nokogiri/html_document.h +10 -0
  9. data/ext/nokogiri/html_sax_parser.c +32 -0
  10. data/ext/nokogiri/html_sax_parser.h +11 -0
  11. data/ext/nokogiri/iconv.dll +0 -0
  12. data/ext/nokogiri/libexslt.dll +0 -0
  13. data/ext/nokogiri/libxml2.dll +0 -0
  14. data/ext/nokogiri/libxslt.dll +0 -0
  15. data/ext/nokogiri/native.c +40 -0
  16. data/ext/nokogiri/native.h +51 -0
  17. data/ext/nokogiri/native.so +0 -0
  18. data/ext/nokogiri/xml_cdata.c +52 -0
  19. data/ext/nokogiri/xml_cdata.h +9 -0
  20. data/ext/nokogiri/xml_document.c +159 -0
  21. data/ext/nokogiri/xml_document.h +10 -0
  22. data/ext/nokogiri/xml_dtd.c +117 -0
  23. data/ext/nokogiri/xml_dtd.h +8 -0
  24. data/ext/nokogiri/xml_node.c +709 -0
  25. data/ext/nokogiri/xml_node.h +15 -0
  26. data/ext/nokogiri/xml_node_set.c +124 -0
  27. data/ext/nokogiri/xml_node_set.h +9 -0
  28. data/ext/nokogiri/xml_reader.c +429 -0
  29. data/ext/nokogiri/xml_reader.h +10 -0
  30. data/ext/nokogiri/xml_sax_parser.c +174 -0
  31. data/ext/nokogiri/xml_sax_parser.h +10 -0
  32. data/ext/nokogiri/xml_syntax_error.c +194 -0
  33. data/ext/nokogiri/xml_syntax_error.h +11 -0
  34. data/ext/nokogiri/xml_text.c +29 -0
  35. data/ext/nokogiri/xml_text.h +9 -0
  36. data/ext/nokogiri/xml_xpath.c +46 -0
  37. data/ext/nokogiri/xml_xpath.h +11 -0
  38. data/ext/nokogiri/xml_xpath_context.c +81 -0
  39. data/ext/nokogiri/xml_xpath_context.h +9 -0
  40. data/ext/nokogiri/xslt_stylesheet.c +108 -0
  41. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  42. data/ext/nokogiri/zlib1.dll +0 -0
  43. data/lib/nokogiri.rb +51 -0
  44. data/lib/nokogiri/css.rb +6 -0
  45. data/lib/nokogiri/css/generated_parser.rb +653 -0
  46. data/lib/nokogiri/css/generated_tokenizer.rb +159 -0
  47. data/lib/nokogiri/css/node.rb +95 -0
  48. data/lib/nokogiri/css/parser.rb +24 -0
  49. data/lib/nokogiri/css/parser.y +198 -0
  50. data/lib/nokogiri/css/tokenizer.rb +9 -0
  51. data/lib/nokogiri/css/tokenizer.rex +63 -0
  52. data/lib/nokogiri/css/xpath_visitor.rb +165 -0
  53. data/lib/nokogiri/decorators.rb +1 -0
  54. data/lib/nokogiri/decorators/hpricot.rb +3 -0
  55. data/lib/nokogiri/decorators/hpricot/node.rb +58 -0
  56. data/lib/nokogiri/decorators/hpricot/node_set.rb +14 -0
  57. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +17 -0
  58. data/lib/nokogiri/hpricot.rb +47 -0
  59. data/lib/nokogiri/html.rb +95 -0
  60. data/lib/nokogiri/html/builder.rb +9 -0
  61. data/lib/nokogiri/html/document.rb +9 -0
  62. data/lib/nokogiri/html/sax/parser.rb +21 -0
  63. data/lib/nokogiri/version.rb +3 -0
  64. data/lib/nokogiri/xml.rb +67 -0
  65. data/lib/nokogiri/xml/after_handler.rb +18 -0
  66. data/lib/nokogiri/xml/before_handler.rb +32 -0
  67. data/lib/nokogiri/xml/builder.rb +79 -0
  68. data/lib/nokogiri/xml/cdata.rb +9 -0
  69. data/lib/nokogiri/xml/document.rb +30 -0
  70. data/lib/nokogiri/xml/dtd.rb +6 -0
  71. data/lib/nokogiri/xml/element.rb +6 -0
  72. data/lib/nokogiri/xml/entity_declaration.rb +9 -0
  73. data/lib/nokogiri/xml/node.rb +195 -0
  74. data/lib/nokogiri/xml/node_set.rb +183 -0
  75. data/lib/nokogiri/xml/notation.rb +6 -0
  76. data/lib/nokogiri/xml/reader.rb +14 -0
  77. data/lib/nokogiri/xml/sax.rb +9 -0
  78. data/lib/nokogiri/xml/sax/document.rb +59 -0
  79. data/lib/nokogiri/xml/sax/parser.rb +33 -0
  80. data/lib/nokogiri/xml/syntax_error.rb +21 -0
  81. data/lib/nokogiri/xml/text.rb +6 -0
  82. data/lib/nokogiri/xml/xpath.rb +6 -0
  83. data/lib/nokogiri/xml/xpath_context.rb +14 -0
  84. data/lib/nokogiri/xslt.rb +11 -0
  85. data/lib/nokogiri/xslt/stylesheet.rb +6 -0
  86. data/nokogiri.gemspec +34 -0
  87. data/test/css/test_nthiness.rb +159 -0
  88. data/test/css/test_parser.rb +224 -0
  89. data/test/css/test_tokenizer.rb +162 -0
  90. data/test/css/test_xpath_visitor.rb +54 -0
  91. data/test/files/staff.xml +59 -0
  92. data/test/files/staff.xslt +32 -0
  93. data/test/files/tlm.html +850 -0
  94. data/test/helper.rb +70 -0
  95. data/test/hpricot/files/basic.xhtml +17 -0
  96. data/test/hpricot/files/boingboing.html +2266 -0
  97. data/test/hpricot/files/cy0.html +3653 -0
  98. data/test/hpricot/files/immob.html +400 -0
  99. data/test/hpricot/files/pace_application.html +1320 -0
  100. data/test/hpricot/files/tenderlove.html +16 -0
  101. data/test/hpricot/files/uswebgen.html +220 -0
  102. data/test/hpricot/files/utf8.html +1054 -0
  103. data/test/hpricot/files/week9.html +1723 -0
  104. data/test/hpricot/files/why.xml +19 -0
  105. data/test/hpricot/load_files.rb +7 -0
  106. data/test/hpricot/test_alter.rb +67 -0
  107. data/test/hpricot/test_builder.rb +27 -0
  108. data/test/hpricot/test_parser.rb +423 -0
  109. data/test/hpricot/test_paths.rb +15 -0
  110. data/test/hpricot/test_preserved.rb +78 -0
  111. data/test/hpricot/test_xml.rb +30 -0
  112. data/test/html/sax/test_parser.rb +27 -0
  113. data/test/html/test_builder.rb +78 -0
  114. data/test/html/test_document.rb +86 -0
  115. data/test/test_convert_xpath.rb +180 -0
  116. data/test/test_nokogiri.rb +36 -0
  117. data/test/test_reader.rb +222 -0
  118. data/test/test_xslt_transforms.rb +29 -0
  119. data/test/xml/sax/test_parser.rb +93 -0
  120. data/test/xml/test_builder.rb +16 -0
  121. data/test/xml/test_cdata.rb +18 -0
  122. data/test/xml/test_document.rb +171 -0
  123. data/test/xml/test_dtd.rb +43 -0
  124. data/test/xml/test_node.rb +223 -0
  125. data/test/xml/test_node_set.rb +116 -0
  126. data/test/xml/test_text.rb +13 -0
  127. metadata +217 -0
@@ -0,0 +1,10 @@
1
+ #ifndef NOKOGIRI_XML_DOCUMENT
2
+ #define NOKOGIRI_XML_DOCUMENT
3
+
4
+ #include <native.h>
5
+
6
+ void init_xml_document();
7
+ VALUE Nokogiri_wrap_xml_document(VALUE klass, xmlDocPtr doc);
8
+
9
+ extern VALUE cNokogiriXmlDocument ;
10
+ #endif
@@ -0,0 +1,117 @@
1
+ #include <xml_dtd.h>
2
+
3
+ static void notation_copier(void *payload, void *data, xmlChar *name)
4
+ {
5
+ VALUE hash = (VALUE)data;
6
+ VALUE klass = rb_const_get(mNokogiriXml, rb_intern("Notation"));
7
+
8
+ xmlNotationPtr c_notation = (xmlNotationPtr)payload;
9
+
10
+ VALUE notation = rb_funcall(klass, rb_intern("new"), 3,
11
+ c_notation->name ? rb_str_new2((const char *)c_notation->name) : Qnil,
12
+ c_notation->PublicID ? rb_str_new2((const char *)c_notation->PublicID) : Qnil,
13
+ c_notation->SystemID ? rb_str_new2((const char *)c_notation->SystemID) : Qnil);
14
+
15
+ rb_hash_aset(hash, rb_str_new2((const char *)name), notation);
16
+ }
17
+
18
+ static void element_copier(void *payload, void *data, xmlChar *name)
19
+ {
20
+ VALUE hash = (VALUE)data;
21
+
22
+ VALUE element = Nokogiri_wrap_xml_node((xmlNodePtr)payload);
23
+
24
+ rb_hash_aset(hash, rb_str_new2((const char *)name), element);
25
+ }
26
+
27
+ /*
28
+ * call-seq:
29
+ * entities
30
+ *
31
+ * Get a hash of the elements for this DTD.
32
+ */
33
+ static VALUE entities(VALUE self)
34
+ {
35
+ xmlDtdPtr dtd;
36
+ Data_Get_Struct(self, xmlDtd, dtd);
37
+
38
+ if(!dtd->entities) return Qnil;
39
+
40
+ VALUE hash = rb_hash_new();
41
+
42
+ xmlHashScan((xmlHashTablePtr)dtd->entities, element_copier, (void *)hash);
43
+
44
+ return hash;
45
+ }
46
+
47
+ /*
48
+ * call-seq:
49
+ * attributes
50
+ *
51
+ * Get a hash of the attributes for this DTD.
52
+ */
53
+ static VALUE attributes(VALUE self)
54
+ {
55
+ xmlDtdPtr dtd;
56
+ Data_Get_Struct(self, xmlDtd, dtd);
57
+
58
+ if(!dtd->attributes) return Qnil;
59
+
60
+ VALUE hash = rb_hash_new();
61
+
62
+ xmlHashScan((xmlHashTablePtr)dtd->attributes, element_copier, (void *)hash);
63
+
64
+ return hash;
65
+ }
66
+
67
+ /*
68
+ * call-seq:
69
+ * notations
70
+ *
71
+ * Get a hash of the notations for this DTD.
72
+ */
73
+ static VALUE notations(VALUE self)
74
+ {
75
+ xmlDtdPtr dtd;
76
+ Data_Get_Struct(self, xmlDtd, dtd);
77
+
78
+ if(!dtd->notations) return Qnil;
79
+
80
+ VALUE hash = rb_hash_new();
81
+
82
+ xmlHashScan((xmlHashTablePtr)dtd->notations, notation_copier, (void *)hash);
83
+
84
+ return hash;
85
+ }
86
+
87
+ /*
88
+ * call-seq:
89
+ * elements
90
+ *
91
+ * Get a hash of the elements for this DTD.
92
+ */
93
+ static VALUE elements(VALUE self)
94
+ {
95
+ xmlDtdPtr dtd;
96
+ Data_Get_Struct(self, xmlDtd, dtd);
97
+
98
+ if(!dtd->elements) return Qnil;
99
+
100
+ VALUE hash = rb_hash_new();
101
+
102
+ xmlHashScan((xmlHashTablePtr)dtd->elements, element_copier, (void *)hash);
103
+
104
+ return hash;
105
+ }
106
+
107
+ void init_xml_dtd()
108
+ {
109
+ VALUE nokogiri = rb_define_module("Nokogiri");
110
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
111
+ VALUE klass = rb_define_class_under(xml, "DTD", cNokogiriXmlNode);
112
+
113
+ rb_define_method(klass, "notations", notations, 0);
114
+ rb_define_method(klass, "elements", elements, 0);
115
+ rb_define_method(klass, "attributes", attributes, 0);
116
+ rb_define_method(klass, "entities", entities, 0);
117
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef NOKOGIRI_XML_DTD
2
+ #define NOKOGIRI_XML_DTD
3
+
4
+ #include <native.h>
5
+
6
+ void init_xml_dtd();
7
+
8
+ #endif
@@ -0,0 +1,709 @@
1
+ #include <xml_node.h>
2
+
3
+ /*
4
+ * call-seq:
5
+ * encode_special_chars(string)
6
+ *
7
+ * Encode any special characters in +string+
8
+ */
9
+ static VALUE encode_special_chars(VALUE self, VALUE string)
10
+ {
11
+ xmlNodePtr node;
12
+ Data_Get_Struct(self, xmlNode, node);
13
+ xmlChar * encoded = xmlEncodeSpecialChars(
14
+ node->doc,
15
+ (const xmlChar *)StringValuePtr(string)
16
+ );
17
+
18
+ VALUE encoded_str = rb_str_new2((const char *)encoded);
19
+ free(encoded);
20
+
21
+ return encoded_str;
22
+ }
23
+
24
+ /*
25
+ * call-seq:
26
+ * internal_subset
27
+ *
28
+ * Get the internal subset
29
+ */
30
+ static VALUE internal_subset(VALUE self)
31
+ {
32
+ xmlNodePtr node;
33
+ xmlDocPtr doc;
34
+ Data_Get_Struct(self, xmlNode, node);
35
+
36
+ if(!node->doc) return Qnil;
37
+
38
+ doc = node->doc;
39
+
40
+ if(!doc->intSubset) return Qnil;
41
+
42
+ return Nokogiri_wrap_xml_node((xmlNodePtr)doc->intSubset);
43
+ }
44
+
45
+ /*
46
+ * call-seq:
47
+ * dup
48
+ *
49
+ * Copy this node
50
+ */
51
+ static VALUE duplicate_node(VALUE self)
52
+ {
53
+ xmlNodePtr node, dup;
54
+ Data_Get_Struct(self, xmlNode, node);
55
+
56
+ dup = xmlCopyNode(node, 1);
57
+ if(dup == NULL) return Qnil;
58
+
59
+ return Nokogiri_wrap_xml_node(dup);
60
+ }
61
+
62
+ /*
63
+ * call-seq:
64
+ * unlink
65
+ *
66
+ * Unlink this node from its current context.
67
+ */
68
+ static VALUE unlink_node(VALUE self)
69
+ {
70
+ xmlNodePtr node;
71
+ Data_Get_Struct(self, xmlNode, node);
72
+ xmlUnlinkNode(node);
73
+ Nokogiri_xml_node_owned_set(node);
74
+ return self;
75
+ }
76
+
77
+ /*
78
+ * call-seq:
79
+ * blank?
80
+ *
81
+ * Is this node blank?
82
+ */
83
+ static VALUE blank_eh(VALUE self)
84
+ {
85
+ xmlNodePtr node;
86
+ Data_Get_Struct(self, xmlNode, node);
87
+ if(1 == xmlIsBlankNode(node))
88
+ return Qtrue;
89
+ return Qfalse;
90
+ }
91
+
92
+ /*
93
+ * call-seq:
94
+ * next_sibling
95
+ *
96
+ * Returns the next sibling node
97
+ */
98
+ static VALUE next_sibling(VALUE self)
99
+ {
100
+ xmlNodePtr node, sibling;
101
+ Data_Get_Struct(self, xmlNode, node);
102
+
103
+ sibling = node->next;
104
+ if(!sibling) return Qnil;
105
+
106
+ return Nokogiri_wrap_xml_node(sibling) ;
107
+ }
108
+
109
+ /*
110
+ * call-seq:
111
+ * previous_sibling
112
+ *
113
+ * Returns the previous sibling node
114
+ */
115
+ static VALUE previous_sibling(VALUE self)
116
+ {
117
+ xmlNodePtr node, sibling;
118
+ Data_Get_Struct(self, xmlNode, node);
119
+
120
+ sibling = node->prev;
121
+ if(!sibling) return Qnil;
122
+
123
+ return Nokogiri_wrap_xml_node(sibling);
124
+ }
125
+
126
+ /*
127
+ * call-seq:
128
+ * replace(new_node)
129
+ *
130
+ * replace node with the new node in the document.
131
+ */
132
+ static VALUE replace(VALUE self, VALUE _new_node)
133
+ {
134
+ xmlNodePtr node, new_node;
135
+ Data_Get_Struct(self, xmlNode, node);
136
+ Data_Get_Struct(_new_node, xmlNode, new_node);
137
+
138
+ xmlReplaceNode(node, new_node);
139
+ Nokogiri_xml_node_owned_set(node);
140
+ Nokogiri_xml_node_owned_set(new_node);
141
+ return self ;
142
+ }
143
+
144
+
145
+ /*
146
+ * call-seq:
147
+ * child
148
+ *
149
+ * Returns the child node
150
+ */
151
+ static VALUE child(VALUE self)
152
+ {
153
+ xmlNodePtr node, child;
154
+ Data_Get_Struct(self, xmlNode, node);
155
+
156
+ child = node->children;
157
+ if(!child) return Qnil;
158
+
159
+ return Nokogiri_wrap_xml_node(child);
160
+ }
161
+
162
+ /*
163
+ * call-seq:
164
+ * key?(attribute)
165
+ *
166
+ * Returns true if +attribute+ is set
167
+ */
168
+ static VALUE key_eh(VALUE self, VALUE attribute)
169
+ {
170
+ xmlNodePtr node;
171
+ Data_Get_Struct(self, xmlNode, node);
172
+ if(xmlHasProp(node, (xmlChar *)StringValuePtr(attribute)))
173
+ return Qtrue;
174
+ return Qfalse;
175
+ }
176
+
177
+ /*
178
+ * call-seq:
179
+ * []=(property, value)
180
+ *
181
+ * Set the +property+ to +value+
182
+ */
183
+ static VALUE set(VALUE self, VALUE property, VALUE value)
184
+ {
185
+ xmlNodePtr node;
186
+ Data_Get_Struct(self, xmlNode, node);
187
+ xmlSetProp(node, (xmlChar *)StringValuePtr(property),
188
+ (xmlChar *)StringValuePtr(value));
189
+
190
+ return value;
191
+ }
192
+
193
+ /*
194
+ * call-seq:
195
+ * remove_attribute(property)
196
+ *
197
+ * remove the property +property+
198
+ */
199
+ static VALUE remove_prop(VALUE self, VALUE property)
200
+ {
201
+ xmlNodePtr node;
202
+ xmlAttrPtr attr ;
203
+ Data_Get_Struct(self, xmlNode, node);
204
+ attr = xmlHasProp(node, (xmlChar *)StringValuePtr(property));
205
+ if (attr) { xmlRemoveProp(attr); }
206
+ return Qnil;
207
+ }
208
+
209
+ /*
210
+ * call-seq:
211
+ * get(attribute)
212
+ *
213
+ * Get the value for +attribute+
214
+ */
215
+ static VALUE get(VALUE self, VALUE attribute)
216
+ {
217
+ xmlNodePtr node;
218
+ xmlChar* propstr ;
219
+ VALUE rval ;
220
+ Data_Get_Struct(self, xmlNode, node);
221
+ propstr = xmlGetProp(node, (xmlChar *)StringValuePtr(attribute));
222
+ rval = rb_str_new2((char *)propstr) ;
223
+ xmlFree(propstr);
224
+ return rval ;
225
+ }
226
+
227
+ /*
228
+ * call-seq:
229
+ * attributes()
230
+ *
231
+ * returns a hash containing the node's attributes.
232
+ */
233
+ static VALUE attributes(VALUE self)
234
+ {
235
+ /* this code in the mode of xmlHasProp() */
236
+ xmlNodePtr node ;
237
+ VALUE attr ;
238
+
239
+ attr = rb_hash_new() ;
240
+ Data_Get_Struct(self, xmlNode, node);
241
+
242
+ Nokogiri_xml_node_properties(node, attr);
243
+
244
+ return attr ;
245
+ }
246
+
247
+ /*
248
+ * call-seq:
249
+ * namespaces()
250
+ *
251
+ * returns a hash containing the node's namespaces.
252
+ */
253
+ static VALUE namespaces(VALUE self)
254
+ {
255
+ /* this code in the mode of xmlHasProp() */
256
+ xmlNodePtr node ;
257
+ VALUE attr ;
258
+
259
+ attr = rb_hash_new() ;
260
+ Data_Get_Struct(self, xmlNode, node);
261
+
262
+ Nokogiri_xml_node_namespaces(node, attr);
263
+
264
+ return attr ;
265
+ }
266
+
267
+ /*
268
+ * call-seq:
269
+ * type
270
+ *
271
+ * Get the type for this node
272
+ */
273
+ static VALUE type(VALUE self)
274
+ {
275
+ xmlNodePtr node;
276
+ Data_Get_Struct(self, xmlNode, node);
277
+ return INT2NUM((int)node->type);
278
+ }
279
+
280
+ /*
281
+ * call-seq:
282
+ * content=
283
+ *
284
+ * Set the content for this Node
285
+ */
286
+ static VALUE set_content(VALUE self, VALUE content)
287
+ {
288
+ xmlNodePtr node;
289
+ Data_Get_Struct(self, xmlNode, node);
290
+ xmlNodeSetContent(node, (xmlChar *)StringValuePtr(content));
291
+ return content;
292
+ }
293
+
294
+ /*
295
+ * call-seq:
296
+ * content
297
+ *
298
+ * Returns the content for this Node
299
+ */
300
+ static VALUE get_content(VALUE self)
301
+ {
302
+ xmlNodePtr node;
303
+ Data_Get_Struct(self, xmlNode, node);
304
+
305
+ xmlChar * content = xmlNodeGetContent(node);
306
+ if(content) {
307
+ VALUE rval = rb_str_new2((char *)content);
308
+ xmlFree(content);
309
+ return rval;
310
+ }
311
+ return Qnil;
312
+ }
313
+
314
+ /*
315
+ * call-seq:
316
+ * parent=(parent_node)
317
+ *
318
+ * Set the parent Node for this Node
319
+ */
320
+ static VALUE set_parent(VALUE self, VALUE parent_node)
321
+ {
322
+ xmlNodePtr node, parent;
323
+ Data_Get_Struct(self, xmlNode, node);
324
+ Data_Get_Struct(parent_node, xmlNode, parent);
325
+
326
+ xmlAddChild(parent, node);
327
+ Nokogiri_xml_node_owned_set(node);
328
+ return parent_node;
329
+ }
330
+
331
+ /*
332
+ * call-seq:
333
+ * parent
334
+ *
335
+ * Get the parent Node for this Node
336
+ */
337
+ static VALUE get_parent(VALUE self)
338
+ {
339
+ xmlNodePtr node, parent;
340
+ Data_Get_Struct(self, xmlNode, node);
341
+
342
+ parent = node->parent;
343
+ if(!parent) return Qnil;
344
+
345
+ return Nokogiri_wrap_xml_node(parent) ;
346
+ }
347
+
348
+ /*
349
+ * call-seq:
350
+ * name=(new_name)
351
+ *
352
+ * Set the name for this Node
353
+ */
354
+ static VALUE set_name(VALUE self, VALUE new_name)
355
+ {
356
+ xmlNodePtr node;
357
+ Data_Get_Struct(self, xmlNode, node);
358
+ xmlNodeSetName(node, (xmlChar*)StringValuePtr(new_name));
359
+ return new_name;
360
+ }
361
+
362
+ /*
363
+ * call-seq:
364
+ * name
365
+ *
366
+ * Returns the name for this Node
367
+ */
368
+ static VALUE get_name(VALUE self)
369
+ {
370
+ xmlNodePtr node;
371
+ Data_Get_Struct(self, xmlNode, node);
372
+ return rb_str_new2((const char *)node->name);
373
+ }
374
+
375
+ /*
376
+ * call-seq:
377
+ * path
378
+ *
379
+ * Returns the path associated with this Node
380
+ */
381
+ static VALUE path(VALUE self)
382
+ {
383
+ xmlNodePtr node;
384
+ xmlChar *path ;
385
+ VALUE rval ;
386
+ Data_Get_Struct(self, xmlNode, node);
387
+
388
+ path = xmlGetNodePath(node);
389
+ rval = rb_str_new2((char *)path);
390
+ xmlFree(path);
391
+ return rval ;
392
+ }
393
+
394
+ /*
395
+ * call-seq:
396
+ * document
397
+ *
398
+ * Returns the Nokogiri::XML::Document associated with this Node
399
+ */
400
+ static VALUE document(VALUE self)
401
+ {
402
+ xmlNodePtr node;
403
+ Data_Get_Struct(self, xmlNode, node);
404
+
405
+ if(!node->doc) return Qnil;
406
+ return (VALUE)node->doc->_private;
407
+ }
408
+
409
+ /*
410
+ * call-seq:
411
+ * add_next_sibling(node)
412
+ *
413
+ * Insert +node+ after this node (as a sibling).
414
+ */
415
+ static VALUE add_next_sibling(VALUE self, VALUE rb_node)
416
+ {
417
+ xmlNodePtr node, new_sibling;
418
+ Data_Get_Struct(self, xmlNode, node);
419
+ Data_Get_Struct(rb_node, xmlNode, new_sibling);
420
+ xmlAddNextSibling(node, new_sibling);
421
+
422
+ rb_funcall(rb_node, rb_intern("decorate!"), 0);
423
+ Nokogiri_xml_node_owned_set(new_sibling);
424
+
425
+ return rb_node;
426
+ }
427
+
428
+ /*
429
+ * call-seq:
430
+ * add_previous_sibling(node)
431
+ *
432
+ * Insert +node+ before this node (as a sibling).
433
+ */
434
+ static VALUE add_previous_sibling(VALUE self, VALUE rb_node)
435
+ {
436
+ xmlNodePtr node, new_sibling;
437
+ Data_Get_Struct(self, xmlNode, node);
438
+ Data_Get_Struct(rb_node, xmlNode, new_sibling);
439
+ xmlAddPrevSibling(node, new_sibling);
440
+
441
+ rb_funcall(rb_node, rb_intern("decorate!"), 0);
442
+ Nokogiri_xml_node_owned_set(new_sibling);
443
+
444
+ return rb_node;
445
+ }
446
+
447
+ /*
448
+ * call-seq:
449
+ * to_xml
450
+ *
451
+ * Returns this node as XML
452
+ */
453
+ static VALUE to_xml(VALUE self)
454
+ {
455
+ xmlBufferPtr buf ;
456
+ xmlNodePtr node ;
457
+ VALUE xml ;
458
+
459
+ Data_Get_Struct(self, xmlNode, node);
460
+
461
+ buf = xmlBufferCreate() ;
462
+ xmlNodeDump(buf, node->doc, node, 2, 1);
463
+ xml = rb_str_new2((char*)buf->content);
464
+ xmlBufferFree(buf);
465
+ return xml ;
466
+ }
467
+
468
+
469
+ /*
470
+ * call-seq:
471
+ * new(name)
472
+ *
473
+ * Create a new node with +name+
474
+ */
475
+ static VALUE new(VALUE klass, VALUE name)
476
+ {
477
+ xmlNodePtr node = xmlNewNode(NULL, (xmlChar *)StringValuePtr(name));
478
+ VALUE rb_node = Nokogiri_wrap_xml_node(node) ;
479
+
480
+ if(rb_block_given_p()) rb_yield(rb_node);
481
+
482
+ Nokogiri_xml_node_owned_set(node);
483
+
484
+ return rb_node;
485
+ }
486
+
487
+
488
+ /*
489
+ * call-seq:
490
+ * new_from_str(string)
491
+ *
492
+ * Create a new node by parsing +string+
493
+ */
494
+ static VALUE new_from_str(VALUE klass, VALUE xml)
495
+ {
496
+ /*
497
+ * I couldn't find a more efficient way to do this. So we create a new
498
+ * document and copy (recursively) the root node.
499
+ */
500
+ VALUE rb_doc ;
501
+ xmlDocPtr doc ;
502
+ xmlNodePtr node ;
503
+
504
+ rb_doc = rb_funcall(cNokogiriXmlDocument, rb_intern("read_memory"), 4,
505
+ xml, Qnil, Qnil, INT2NUM(0));
506
+ Data_Get_Struct(rb_doc, xmlDoc, doc);
507
+ node = xmlCopyNode(xmlDocGetRootElement(doc), 1); /* 1 => recursive */
508
+ return Nokogiri_wrap_xml_node(node);
509
+ }
510
+
511
+ static void deallocate(xmlNodePtr node)
512
+ {
513
+ if (! Nokogiri_xml_node_owned_get(node)) {
514
+ NOKOGIRI_DEBUG_START_NODE(node);
515
+ xmlFreeNode(node);
516
+ NOKOGIRI_DEBUG_END(node);
517
+ }
518
+ }
519
+
520
+ static void gc_mark_node(xmlNodePtr node)
521
+ {
522
+ xmlNodePtr child ;
523
+ /* mark document */
524
+ if (node && node->doc && node->doc->_private)
525
+ rb_gc_mark((VALUE)node->doc->_private);
526
+ /* mark parent node */
527
+ if (node && node->parent && node->parent->_private)
528
+ rb_gc_mark((VALUE)node->parent->_private);
529
+ /* mark children nodes */
530
+ for (child = node->children ; child ; child = child->next) {
531
+ if (child->_private)
532
+ rb_gc_mark((VALUE)child->_private);
533
+ }
534
+ /* mark sibling nodes */
535
+ if (node->next && node->next->_private)
536
+ rb_gc_mark((VALUE)node->next->_private) ;
537
+ if (node->prev && node->prev->_private)
538
+ rb_gc_mark((VALUE)node->prev->_private) ;
539
+ }
540
+
541
+ VALUE Nokogiri_wrap_xml_node(xmlNodePtr node)
542
+ {
543
+ if (node->_private)
544
+ return (VALUE)node->_private ;
545
+
546
+ VALUE rb_node = Qnil;
547
+
548
+ switch(node->type)
549
+ {
550
+ VALUE klass;
551
+
552
+ case XML_TEXT_NODE:
553
+ klass = rb_const_get(mNokogiriXml, rb_intern("Text"));
554
+ rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
555
+ break;
556
+ case XML_ELEMENT_NODE:
557
+ klass = rb_const_get(mNokogiriXml, rb_intern("Element"));
558
+ rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
559
+ break;
560
+ case XML_ENTITY_DECL:
561
+ klass = rb_const_get(mNokogiriXml, rb_intern("EntityDeclaration"));
562
+ rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
563
+ break;
564
+ case XML_CDATA_SECTION_NODE:
565
+ klass = rb_const_get(mNokogiriXml, rb_intern("CDATA"));
566
+ rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
567
+ break;
568
+ case XML_DTD_NODE:
569
+ klass = rb_const_get(mNokogiriXml, rb_intern("DTD"));
570
+ rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
571
+ break;
572
+ default:
573
+ rb_node = Data_Wrap_Struct(cNokogiriXmlNode, gc_mark_node, deallocate, node) ;
574
+ }
575
+
576
+ node->_private = (void*)rb_node ;
577
+ rb_funcall(rb_node, rb_intern("decorate!"), 0);
578
+ Nokogiri_xml_node_owned_set(node);
579
+ return rb_node ;
580
+ }
581
+
582
+
583
+ void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_hash)
584
+ {
585
+ xmlAttrPtr prop;
586
+ xmlChar* propstr ;
587
+ prop = node->properties ;
588
+ while (prop != NULL) {
589
+ propstr = xmlGetProp(node, prop->name) ;
590
+ rb_hash_aset(attr_hash, rb_str_new2((const char*)prop->name),
591
+ rb_str_new2((char*)propstr));
592
+ xmlFree(propstr);
593
+ prop = prop->next ;
594
+ }
595
+ }
596
+
597
+
598
+ #define XMLNS_PREFIX "xmlns"
599
+ #define XMLNS_PREFIX_LEN 6 /* including either colon or \0 */
600
+ #define XMLNS_BUFFER_LEN 128
601
+ void Nokogiri_xml_node_namespaces(xmlNodePtr node, VALUE attr_hash)
602
+ {
603
+ xmlNsPtr ns;
604
+ static char buffer[XMLNS_BUFFER_LEN] ;
605
+ char *key ;
606
+ size_t keylen ;
607
+
608
+ if (node->type != XML_ELEMENT_NODE) return ;
609
+
610
+ ns = node->nsDef;
611
+ while (ns != NULL) {
612
+
613
+ keylen = XMLNS_PREFIX_LEN + (ns->prefix ? (strlen((const char*)ns->prefix) + 1) : 0) ;
614
+ if (keylen > XMLNS_BUFFER_LEN) {
615
+ key = (char*)malloc(keylen) ;
616
+ } else {
617
+ key = buffer ;
618
+ }
619
+
620
+ if (ns->prefix) {
621
+ sprintf(key, "%s:%s", XMLNS_PREFIX, ns->prefix);
622
+ } else {
623
+ sprintf(key, "%s", XMLNS_PREFIX);
624
+ }
625
+
626
+ rb_hash_aset(attr_hash, rb_str_new2(key), rb_str_new2((const char*)ns->href)) ;
627
+ if (key != buffer) {
628
+ free(key);
629
+ }
630
+ ns = ns->next ;
631
+ }
632
+ }
633
+
634
+
635
+ void Nokogiri_xml_node_owned_set(xmlNodePtr node)
636
+ {
637
+ VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@owned"));
638
+ rb_hash_aset(hash, INT2NUM((long)node), node->parent ? Qtrue : Qfalse) ;
639
+ }
640
+
641
+ int Nokogiri_xml_node_owned_get(xmlNodePtr node)
642
+ {
643
+ VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@owned"));
644
+ VALUE q = rb_hash_aref(hash, INT2NUM((long)node)) ;
645
+ return q == Qtrue ? Qtrue : Qfalse ;
646
+ }
647
+
648
+ /*
649
+ * call-seq:
650
+ * owned?
651
+ *
652
+ * Is this node owned by a document?
653
+ */
654
+ static VALUE owned_eh(VALUE self)
655
+ {
656
+ xmlNodePtr node ;
657
+ VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@owned"));
658
+ Data_Get_Struct(self, xmlNode, node);
659
+ return rb_hash_aref(hash, INT2NUM((long)node)) == Qtrue ? Qtrue : Qfalse ;
660
+ }
661
+
662
+
663
+ VALUE cNokogiriXmlNode ;
664
+ void init_xml_node()
665
+ {
666
+ /*
667
+ * HACK. This is so that rdoc will work with this C file.
668
+ */
669
+ /*
670
+ VALUE nokogiri = rb_define_module("Nokogiri");
671
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
672
+ VALUE klass = rb_define_class_under(xml, "Node", rb_cObject);
673
+ */
674
+
675
+ VALUE klass = cNokogiriXmlNode = rb_const_get(mNokogiriXml, rb_intern("Node"));
676
+
677
+ rb_define_singleton_method(klass, "new", new, 1);
678
+ rb_define_singleton_method(klass, "new_from_str", new_from_str, 1);
679
+
680
+ rb_define_method(klass, "document", document, 0);
681
+ rb_define_method(klass, "name", get_name, 0);
682
+ rb_define_method(klass, "name=", set_name, 1);
683
+ rb_define_method(klass, "parent=", set_parent, 1);
684
+ rb_define_method(klass, "parent", get_parent, 0);
685
+ rb_define_method(klass, "child", child, 0);
686
+ rb_define_method(klass, "next_sibling", next_sibling, 0);
687
+ rb_define_method(klass, "previous_sibling", previous_sibling, 0);
688
+ rb_define_method(klass, "replace", replace, 1);
689
+ rb_define_method(klass, "type", type, 0);
690
+ rb_define_method(klass, "content", get_content, 0);
691
+ rb_define_method(klass, "path", path, 0);
692
+ rb_define_method(klass, "key?", key_eh, 1);
693
+ rb_define_method(klass, "blank?", blank_eh, 0);
694
+ rb_define_method(klass, "[]=", set, 2);
695
+ rb_define_method(klass, "remove_attribute", remove_prop, 1);
696
+ rb_define_method(klass, "attributes", attributes, 0);
697
+ rb_define_method(klass, "namespaces", namespaces, 0);
698
+ rb_define_method(klass, "add_previous_sibling", add_previous_sibling, 1);
699
+ rb_define_method(klass, "add_next_sibling", add_next_sibling, 1);
700
+ rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
701
+ rb_define_method(klass, "to_xml", to_xml, 0);
702
+ rb_define_method(klass, "dup", duplicate_node, 0);
703
+ rb_define_method(klass, "unlink", unlink_node, 0);
704
+ rb_define_method(klass, "internal_subset", internal_subset, 0);
705
+
706
+ rb_define_private_method(klass, "native_content=", set_content, 1);
707
+ rb_define_private_method(klass, "get", get, 1);
708
+ rb_define_private_method(klass, "owned?", owned_eh, 0);
709
+ }