glebm-nokogiri 1.4.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (277) hide show
  1. data/.autotest +26 -0
  2. data/CHANGELOG.ja.rdoc +411 -0
  3. data/CHANGELOG.rdoc +397 -0
  4. data/Manifest.txt +276 -0
  5. data/README.ja.rdoc +106 -0
  6. data/README.rdoc +132 -0
  7. data/Rakefile +183 -0
  8. data/bin/nokogiri +49 -0
  9. data/deps.rip +5 -0
  10. data/ext/nokogiri/extconf.rb +97 -0
  11. data/ext/nokogiri/html_document.c +154 -0
  12. data/ext/nokogiri/html_document.h +10 -0
  13. data/ext/nokogiri/html_element_description.c +276 -0
  14. data/ext/nokogiri/html_element_description.h +10 -0
  15. data/ext/nokogiri/html_entity_lookup.c +32 -0
  16. data/ext/nokogiri/html_entity_lookup.h +8 -0
  17. data/ext/nokogiri/html_sax_parser_context.c +94 -0
  18. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  19. data/ext/nokogiri/nokogiri.c +95 -0
  20. data/ext/nokogiri/nokogiri.h +153 -0
  21. data/ext/nokogiri/xml_attr.c +94 -0
  22. data/ext/nokogiri/xml_attr.h +9 -0
  23. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  24. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  25. data/ext/nokogiri/xml_cdata.c +56 -0
  26. data/ext/nokogiri/xml_cdata.h +9 -0
  27. data/ext/nokogiri/xml_comment.c +54 -0
  28. data/ext/nokogiri/xml_comment.h +9 -0
  29. data/ext/nokogiri/xml_document.c +464 -0
  30. data/ext/nokogiri/xml_document.h +23 -0
  31. data/ext/nokogiri/xml_document_fragment.c +48 -0
  32. data/ext/nokogiri/xml_document_fragment.h +10 -0
  33. data/ext/nokogiri/xml_dtd.c +202 -0
  34. data/ext/nokogiri/xml_dtd.h +10 -0
  35. data/ext/nokogiri/xml_element_content.c +123 -0
  36. data/ext/nokogiri/xml_element_content.h +10 -0
  37. data/ext/nokogiri/xml_element_decl.c +69 -0
  38. data/ext/nokogiri/xml_element_decl.h +9 -0
  39. data/ext/nokogiri/xml_encoding_handler.c +79 -0
  40. data/ext/nokogiri/xml_encoding_handler.h +8 -0
  41. data/ext/nokogiri/xml_entity_decl.c +110 -0
  42. data/ext/nokogiri/xml_entity_decl.h +10 -0
  43. data/ext/nokogiri/xml_entity_reference.c +52 -0
  44. data/ext/nokogiri/xml_entity_reference.h +9 -0
  45. data/ext/nokogiri/xml_io.c +31 -0
  46. data/ext/nokogiri/xml_io.h +11 -0
  47. data/ext/nokogiri/xml_namespace.c +84 -0
  48. data/ext/nokogiri/xml_namespace.h +13 -0
  49. data/ext/nokogiri/xml_node.c +1347 -0
  50. data/ext/nokogiri/xml_node.h +13 -0
  51. data/ext/nokogiri/xml_node_set.c +418 -0
  52. data/ext/nokogiri/xml_node_set.h +9 -0
  53. data/ext/nokogiri/xml_processing_instruction.c +56 -0
  54. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  55. data/ext/nokogiri/xml_reader.c +665 -0
  56. data/ext/nokogiri/xml_reader.h +10 -0
  57. data/ext/nokogiri/xml_relax_ng.c +168 -0
  58. data/ext/nokogiri/xml_relax_ng.h +9 -0
  59. data/ext/nokogiri/xml_sax_parser.c +286 -0
  60. data/ext/nokogiri/xml_sax_parser.h +39 -0
  61. data/ext/nokogiri/xml_sax_parser_context.c +159 -0
  62. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  63. data/ext/nokogiri/xml_sax_push_parser.c +115 -0
  64. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  65. data/ext/nokogiri/xml_schema.c +205 -0
  66. data/ext/nokogiri/xml_schema.h +9 -0
  67. data/ext/nokogiri/xml_syntax_error.c +58 -0
  68. data/ext/nokogiri/xml_syntax_error.h +13 -0
  69. data/ext/nokogiri/xml_text.c +50 -0
  70. data/ext/nokogiri/xml_text.h +9 -0
  71. data/ext/nokogiri/xml_xpath_context.c +276 -0
  72. data/ext/nokogiri/xml_xpath_context.h +9 -0
  73. data/ext/nokogiri/xslt_stylesheet.c +142 -0
  74. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  75. data/lib/nokogiri.rb +133 -0
  76. data/lib/nokogiri/css.rb +25 -0
  77. data/lib/nokogiri/css/generated_parser.rb +669 -0
  78. data/lib/nokogiri/css/generated_tokenizer.rb +145 -0
  79. data/lib/nokogiri/css/node.rb +99 -0
  80. data/lib/nokogiri/css/parser.rb +82 -0
  81. data/lib/nokogiri/css/parser.y +232 -0
  82. data/lib/nokogiri/css/syntax_error.rb +7 -0
  83. data/lib/nokogiri/css/tokenizer.rb +7 -0
  84. data/lib/nokogiri/css/tokenizer.rex +55 -0
  85. data/lib/nokogiri/css/xpath_visitor.rb +169 -0
  86. data/lib/nokogiri/decorators/slop.rb +33 -0
  87. data/lib/nokogiri/ffi/encoding_handler.rb +42 -0
  88. data/lib/nokogiri/ffi/html/document.rb +28 -0
  89. data/lib/nokogiri/ffi/html/element_description.rb +81 -0
  90. data/lib/nokogiri/ffi/html/entity_lookup.rb +16 -0
  91. data/lib/nokogiri/ffi/html/sax/parser_context.rb +38 -0
  92. data/lib/nokogiri/ffi/io_callbacks.rb +42 -0
  93. data/lib/nokogiri/ffi/libxml.rb +386 -0
  94. data/lib/nokogiri/ffi/structs/common_node.rb +38 -0
  95. data/lib/nokogiri/ffi/structs/html_elem_desc.rb +24 -0
  96. data/lib/nokogiri/ffi/structs/html_entity_desc.rb +13 -0
  97. data/lib/nokogiri/ffi/structs/xml_alloc.rb +16 -0
  98. data/lib/nokogiri/ffi/structs/xml_attr.rb +19 -0
  99. data/lib/nokogiri/ffi/structs/xml_attribute.rb +27 -0
  100. data/lib/nokogiri/ffi/structs/xml_buffer.rb +16 -0
  101. data/lib/nokogiri/ffi/structs/xml_char_encoding_handler.rb +11 -0
  102. data/lib/nokogiri/ffi/structs/xml_document.rb +117 -0
  103. data/lib/nokogiri/ffi/structs/xml_dtd.rb +28 -0
  104. data/lib/nokogiri/ffi/structs/xml_element.rb +26 -0
  105. data/lib/nokogiri/ffi/structs/xml_element_content.rb +17 -0
  106. data/lib/nokogiri/ffi/structs/xml_entity.rb +32 -0
  107. data/lib/nokogiri/ffi/structs/xml_enumeration.rb +12 -0
  108. data/lib/nokogiri/ffi/structs/xml_node.rb +28 -0
  109. data/lib/nokogiri/ffi/structs/xml_node_set.rb +53 -0
  110. data/lib/nokogiri/ffi/structs/xml_notation.rb +11 -0
  111. data/lib/nokogiri/ffi/structs/xml_ns.rb +15 -0
  112. data/lib/nokogiri/ffi/structs/xml_parser_context.rb +19 -0
  113. data/lib/nokogiri/ffi/structs/xml_relax_ng.rb +14 -0
  114. data/lib/nokogiri/ffi/structs/xml_sax_handler.rb +51 -0
  115. data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +124 -0
  116. data/lib/nokogiri/ffi/structs/xml_schema.rb +13 -0
  117. data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +31 -0
  118. data/lib/nokogiri/ffi/structs/xml_text_reader.rb +12 -0
  119. data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +38 -0
  120. data/lib/nokogiri/ffi/structs/xml_xpath_object.rb +35 -0
  121. data/lib/nokogiri/ffi/structs/xml_xpath_parser_context.rb +20 -0
  122. data/lib/nokogiri/ffi/structs/xslt_stylesheet.rb +13 -0
  123. data/lib/nokogiri/ffi/weak_bucket.rb +40 -0
  124. data/lib/nokogiri/ffi/xml/attr.rb +41 -0
  125. data/lib/nokogiri/ffi/xml/attribute_decl.rb +27 -0
  126. data/lib/nokogiri/ffi/xml/cdata.rb +19 -0
  127. data/lib/nokogiri/ffi/xml/comment.rb +18 -0
  128. data/lib/nokogiri/ffi/xml/document.rb +162 -0
  129. data/lib/nokogiri/ffi/xml/document_fragment.rb +21 -0
  130. data/lib/nokogiri/ffi/xml/dtd.rb +67 -0
  131. data/lib/nokogiri/ffi/xml/element_content.rb +43 -0
  132. data/lib/nokogiri/ffi/xml/element_decl.rb +19 -0
  133. data/lib/nokogiri/ffi/xml/entity_decl.rb +36 -0
  134. data/lib/nokogiri/ffi/xml/entity_reference.rb +19 -0
  135. data/lib/nokogiri/ffi/xml/namespace.rb +44 -0
  136. data/lib/nokogiri/ffi/xml/node.rb +556 -0
  137. data/lib/nokogiri/ffi/xml/node_set.rb +149 -0
  138. data/lib/nokogiri/ffi/xml/processing_instruction.rb +20 -0
  139. data/lib/nokogiri/ffi/xml/reader.rb +232 -0
  140. data/lib/nokogiri/ffi/xml/relax_ng.rb +85 -0
  141. data/lib/nokogiri/ffi/xml/sax/parser.rb +135 -0
  142. data/lib/nokogiri/ffi/xml/sax/parser_context.rb +67 -0
  143. data/lib/nokogiri/ffi/xml/sax/push_parser.rb +51 -0
  144. data/lib/nokogiri/ffi/xml/schema.rb +109 -0
  145. data/lib/nokogiri/ffi/xml/syntax_error.rb +98 -0
  146. data/lib/nokogiri/ffi/xml/text.rb +18 -0
  147. data/lib/nokogiri/ffi/xml/xpath.rb +9 -0
  148. data/lib/nokogiri/ffi/xml/xpath_context.rb +148 -0
  149. data/lib/nokogiri/ffi/xslt/stylesheet.rb +53 -0
  150. data/lib/nokogiri/html.rb +35 -0
  151. data/lib/nokogiri/html/builder.rb +35 -0
  152. data/lib/nokogiri/html/document.rb +90 -0
  153. data/lib/nokogiri/html/document_fragment.rb +36 -0
  154. data/lib/nokogiri/html/element_description.rb +23 -0
  155. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  156. data/lib/nokogiri/html/sax/parser.rb +48 -0
  157. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  158. data/lib/nokogiri/syntax_error.rb +4 -0
  159. data/lib/nokogiri/version.rb +37 -0
  160. data/lib/nokogiri/version_warning.rb +14 -0
  161. data/lib/nokogiri/xml.rb +67 -0
  162. data/lib/nokogiri/xml/attr.rb +14 -0
  163. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  164. data/lib/nokogiri/xml/builder.rb +418 -0
  165. data/lib/nokogiri/xml/cdata.rb +11 -0
  166. data/lib/nokogiri/xml/character_data.rb +7 -0
  167. data/lib/nokogiri/xml/document.rb +194 -0
  168. data/lib/nokogiri/xml/document_fragment.rb +77 -0
  169. data/lib/nokogiri/xml/dtd.rb +11 -0
  170. data/lib/nokogiri/xml/element_content.rb +36 -0
  171. data/lib/nokogiri/xml/element_decl.rb +13 -0
  172. data/lib/nokogiri/xml/entity_decl.rb +19 -0
  173. data/lib/nokogiri/xml/namespace.rb +13 -0
  174. data/lib/nokogiri/xml/node.rb +793 -0
  175. data/lib/nokogiri/xml/node/save_options.rb +42 -0
  176. data/lib/nokogiri/xml/node_set.rb +325 -0
  177. data/lib/nokogiri/xml/notation.rb +6 -0
  178. data/lib/nokogiri/xml/parse_options.rb +85 -0
  179. data/lib/nokogiri/xml/pp.rb +2 -0
  180. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  181. data/lib/nokogiri/xml/pp/node.rb +56 -0
  182. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  183. data/lib/nokogiri/xml/reader.rb +74 -0
  184. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  185. data/lib/nokogiri/xml/sax.rb +4 -0
  186. data/lib/nokogiri/xml/sax/document.rb +160 -0
  187. data/lib/nokogiri/xml/sax/parser.rb +115 -0
  188. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  189. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  190. data/lib/nokogiri/xml/schema.rb +57 -0
  191. data/lib/nokogiri/xml/syntax_error.rb +47 -0
  192. data/lib/nokogiri/xml/text.rb +9 -0
  193. data/lib/nokogiri/xml/xpath.rb +10 -0
  194. data/lib/nokogiri/xml/xpath/syntax_error.rb +11 -0
  195. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  196. data/lib/nokogiri/xslt.rb +48 -0
  197. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  198. data/lib/xsd/xmlparser/nokogiri.rb +90 -0
  199. data/tasks/cross_compile.rb +158 -0
  200. data/tasks/test.rb +94 -0
  201. data/test/css/test_nthiness.rb +159 -0
  202. data/test/css/test_parser.rb +282 -0
  203. data/test/css/test_tokenizer.rb +190 -0
  204. data/test/css/test_xpath_visitor.rb +85 -0
  205. data/test/ffi/test_document.rb +35 -0
  206. data/test/files/2ch.html +108 -0
  207. data/test/files/address_book.rlx +12 -0
  208. data/test/files/address_book.xml +10 -0
  209. data/test/files/bar/bar.xsd +4 -0
  210. data/test/files/dont_hurt_em_why.xml +422 -0
  211. data/test/files/exslt.xml +8 -0
  212. data/test/files/exslt.xslt +35 -0
  213. data/test/files/foo/foo.xsd +4 -0
  214. data/test/files/po.xml +32 -0
  215. data/test/files/po.xsd +66 -0
  216. data/test/files/shift_jis.html +10 -0
  217. data/test/files/shift_jis.xml +5 -0
  218. data/test/files/snuggles.xml +3 -0
  219. data/test/files/staff.dtd +10 -0
  220. data/test/files/staff.xml +59 -0
  221. data/test/files/staff.xslt +32 -0
  222. data/test/files/tlm.html +850 -0
  223. data/test/files/valid_bar.xml +2 -0
  224. data/test/helper.rb +169 -0
  225. data/test/html/sax/test_parser.rb +74 -0
  226. data/test/html/sax/test_parser_context.rb +48 -0
  227. data/test/html/test_builder.rb +164 -0
  228. data/test/html/test_document.rb +398 -0
  229. data/test/html/test_document_encoding.rb +77 -0
  230. data/test/html/test_document_fragment.rb +182 -0
  231. data/test/html/test_element_description.rb +98 -0
  232. data/test/html/test_named_characters.rb +14 -0
  233. data/test/html/test_node.rb +181 -0
  234. data/test/html/test_node_encoding.rb +27 -0
  235. data/test/test_convert_xpath.rb +135 -0
  236. data/test/test_css_cache.rb +45 -0
  237. data/test/test_encoding_handler.rb +46 -0
  238. data/test/test_memory_leak.rb +87 -0
  239. data/test/test_nokogiri.rb +138 -0
  240. data/test/test_reader.rb +386 -0
  241. data/test/test_soap4r_sax.rb +52 -0
  242. data/test/test_xslt_transforms.rb +188 -0
  243. data/test/xml/node/test_save_options.rb +20 -0
  244. data/test/xml/node/test_subclass.rb +44 -0
  245. data/test/xml/sax/test_parser.rb +307 -0
  246. data/test/xml/sax/test_parser_context.rb +63 -0
  247. data/test/xml/sax/test_push_parser.rb +139 -0
  248. data/test/xml/test_attr.rb +38 -0
  249. data/test/xml/test_attribute_decl.rb +82 -0
  250. data/test/xml/test_builder.rb +210 -0
  251. data/test/xml/test_cdata.rb +50 -0
  252. data/test/xml/test_comment.rb +29 -0
  253. data/test/xml/test_document.rb +668 -0
  254. data/test/xml/test_document_encoding.rb +26 -0
  255. data/test/xml/test_document_fragment.rb +180 -0
  256. data/test/xml/test_dtd.rb +82 -0
  257. data/test/xml/test_dtd_encoding.rb +33 -0
  258. data/test/xml/test_element_content.rb +56 -0
  259. data/test/xml/test_element_decl.rb +73 -0
  260. data/test/xml/test_entity_decl.rb +120 -0
  261. data/test/xml/test_entity_reference.rb +21 -0
  262. data/test/xml/test_namespace.rb +68 -0
  263. data/test/xml/test_node.rb +865 -0
  264. data/test/xml/test_node_attributes.rb +34 -0
  265. data/test/xml/test_node_encoding.rb +107 -0
  266. data/test/xml/test_node_reparenting.rb +293 -0
  267. data/test/xml/test_node_set.rb +649 -0
  268. data/test/xml/test_parse_options.rb +52 -0
  269. data/test/xml/test_processing_instruction.rb +30 -0
  270. data/test/xml/test_reader_encoding.rb +126 -0
  271. data/test/xml/test_relax_ng.rb +60 -0
  272. data/test/xml/test_schema.rb +89 -0
  273. data/test/xml/test_syntax_error.rb +12 -0
  274. data/test/xml/test_text.rb +38 -0
  275. data/test/xml/test_unparented_node.rb +381 -0
  276. data/test/xml/test_xpath.rb +138 -0
  277. metadata +533 -0
@@ -0,0 +1,9 @@
1
+ #ifndef NOKOGIRI_XML_ELEMENT_DECL
2
+ #define NOKOGIRI_XML_ELEMENT_DECL
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_element_decl();
7
+
8
+ extern VALUE cNokogiriXmlElementDecl;
9
+ #endif
@@ -0,0 +1,79 @@
1
+ #include <xml_encoding_handler.h>
2
+
3
+ /*
4
+ * call-seq: Nokogiri::EncodingHandler.[](name)
5
+ *
6
+ * Get the encoding handler for +name+
7
+ */
8
+ static VALUE get(VALUE klass, VALUE key)
9
+ {
10
+ xmlCharEncodingHandlerPtr handler;
11
+
12
+ handler = xmlFindCharEncodingHandler(StringValuePtr(key));
13
+ if(handler)
14
+ return Data_Wrap_Struct(klass, NULL, NULL, handler);
15
+
16
+ return Qnil;
17
+ }
18
+
19
+ /*
20
+ * call-seq: Nokogiri::EncodingHandler.delete(name)
21
+ *
22
+ * Delete the encoding alias named +name+
23
+ */
24
+ static VALUE delete(VALUE klass, VALUE name)
25
+ {
26
+ if(xmlDelEncodingAlias(StringValuePtr(name))) return Qnil;
27
+
28
+ return Qtrue;
29
+ }
30
+
31
+ /*
32
+ * call-seq: Nokogiri::EncodingHandler.alias(from, to)
33
+ *
34
+ * Alias encoding handler with name +from+ to name +to+
35
+ */
36
+ static VALUE alias(VALUE klass, VALUE from, VALUE to)
37
+ {
38
+ xmlAddEncodingAlias(StringValuePtr(from), StringValuePtr(to));
39
+
40
+ return to;
41
+ }
42
+
43
+ /*
44
+ * call-seq: Nokogiri::EncodingHandler.clear_aliases!
45
+ *
46
+ * Remove all encoding aliases.
47
+ */
48
+ static VALUE clear_aliases(VALUE klass)
49
+ {
50
+ xmlCleanupEncodingAliases();
51
+
52
+ return klass;
53
+ }
54
+
55
+ /*
56
+ * call-seq: name
57
+ *
58
+ * Get the name of this EncodingHandler
59
+ */
60
+ static VALUE name(VALUE self)
61
+ {
62
+ xmlCharEncodingHandlerPtr handler;
63
+
64
+ Data_Get_Struct(self, xmlCharEncodingHandler, handler);
65
+
66
+ return NOKOGIRI_STR_NEW2(handler->name);
67
+ }
68
+
69
+ void init_xml_encoding_handler()
70
+ {
71
+ VALUE nokogiri = rb_define_module("Nokogiri");
72
+ VALUE klass = rb_define_class_under(nokogiri, "EncodingHandler", rb_cObject);
73
+
74
+ rb_define_singleton_method(klass, "[]", get, 1);
75
+ rb_define_singleton_method(klass, "delete", delete, 1);
76
+ rb_define_singleton_method(klass, "alias", alias, 2);
77
+ rb_define_singleton_method(klass, "clear_aliases!", clear_aliases, 0);
78
+ rb_define_method(klass, "name", name, 0);
79
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef NOKOGIRI_XML_ENCODING_HANDLER
2
+ #define NOKOGIRI_XML_ENCODING_HANDLER
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_encoding_handler();
7
+
8
+ #endif
@@ -0,0 +1,110 @@
1
+ #include <xml_entity_decl.h>
2
+
3
+ /*
4
+ * call-seq:
5
+ * original_content
6
+ *
7
+ * Get the original_content before ref substitution
8
+ */
9
+ static VALUE original_content(VALUE self)
10
+ {
11
+ xmlEntityPtr node;
12
+ Data_Get_Struct(self, xmlEntity, node);
13
+
14
+ if(!node->orig) return Qnil;
15
+
16
+ return NOKOGIRI_STR_NEW2(node->orig);
17
+ }
18
+
19
+ /*
20
+ * call-seq:
21
+ * content
22
+ *
23
+ * Get the content
24
+ */
25
+ static VALUE get_content(VALUE self)
26
+ {
27
+ xmlEntityPtr node;
28
+ Data_Get_Struct(self, xmlEntity, node);
29
+
30
+ if(!node->content) return Qnil;
31
+
32
+ return NOKOGIRI_STR_NEW(node->content, node->length);
33
+ }
34
+
35
+ /*
36
+ * call-seq:
37
+ * entity_type
38
+ *
39
+ * Get the entity type
40
+ */
41
+ static VALUE entity_type(VALUE self)
42
+ {
43
+ xmlEntityPtr node;
44
+ Data_Get_Struct(self, xmlEntity, node);
45
+
46
+ return INT2NUM((int)node->etype);
47
+ }
48
+
49
+ /*
50
+ * call-seq:
51
+ * external_id
52
+ *
53
+ * Get the external identifier for PUBLIC
54
+ */
55
+ static VALUE external_id(VALUE self)
56
+ {
57
+ xmlEntityPtr node;
58
+ Data_Get_Struct(self, xmlEntity, node);
59
+
60
+ if(!node->ExternalID) return Qnil;
61
+
62
+ return NOKOGIRI_STR_NEW2(node->ExternalID);
63
+ }
64
+
65
+ /*
66
+ * call-seq:
67
+ * system_id
68
+ *
69
+ * Get the URI for a SYSTEM or PUBLIC Entity
70
+ */
71
+ static VALUE system_id(VALUE self)
72
+ {
73
+ xmlEntityPtr node;
74
+ Data_Get_Struct(self, xmlEntity, node);
75
+
76
+ if(!node->SystemID) return Qnil;
77
+
78
+ return NOKOGIRI_STR_NEW2(node->SystemID);
79
+ }
80
+
81
+ VALUE cNokogiriXmlEntityDecl;
82
+
83
+ void init_xml_entity_decl()
84
+ {
85
+ VALUE nokogiri = rb_define_module("Nokogiri");
86
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
87
+ VALUE node = rb_define_class_under(xml, "Node", rb_cObject);
88
+ VALUE klass = rb_define_class_under(xml, "EntityDecl", node);
89
+
90
+ cNokogiriXmlEntityDecl = klass;
91
+
92
+ rb_define_method(klass, "original_content", original_content, 0);
93
+ rb_define_method(klass, "content", get_content, 0);
94
+ rb_define_method(klass, "entity_type", entity_type, 0);
95
+ rb_define_method(klass, "external_id", external_id, 0);
96
+ rb_define_method(klass, "system_id", system_id, 0);
97
+
98
+ rb_const_set(cNokogiriXmlEntityDecl, rb_intern("INTERNAL_GENERAL"),
99
+ INT2NUM(XML_INTERNAL_GENERAL_ENTITY));
100
+ rb_const_set(cNokogiriXmlEntityDecl, rb_intern("EXTERNAL_GENERAL_PARSED"),
101
+ INT2NUM(XML_EXTERNAL_GENERAL_PARSED_ENTITY));
102
+ rb_const_set(cNokogiriXmlEntityDecl, rb_intern("EXTERNAL_GENERAL_UNPARSED"),
103
+ INT2NUM(XML_EXTERNAL_GENERAL_UNPARSED_ENTITY));
104
+ rb_const_set(cNokogiriXmlEntityDecl, rb_intern("INTERNAL_PARAMETER"),
105
+ INT2NUM(XML_INTERNAL_PARAMETER_ENTITY));
106
+ rb_const_set(cNokogiriXmlEntityDecl, rb_intern("EXTERNAL_PARAMETER"),
107
+ INT2NUM(XML_EXTERNAL_PARAMETER_ENTITY));
108
+ rb_const_set(cNokogiriXmlEntityDecl, rb_intern("INTERNAL_PREDEFINED"),
109
+ INT2NUM(XML_INTERNAL_PREDEFINED_ENTITY));
110
+ }
@@ -0,0 +1,10 @@
1
+ #ifndef NOKOGIRI_XML_ENTITY_DECL
2
+ #define NOKOGIRI_XML_ENTITY_DECL
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_entity_decl();
7
+
8
+ extern VALUE cNokogiriXmlEntityDecl;
9
+ #endif
10
+
@@ -0,0 +1,52 @@
1
+ #include <xml_entity_reference.h>
2
+
3
+ /*
4
+ * call-seq:
5
+ * new(document, content)
6
+ *
7
+ * Create a new EntityReference element on the +document+ with +name+
8
+ */
9
+ static VALUE new(int argc, VALUE *argv, VALUE klass)
10
+ {
11
+ xmlDocPtr xml_doc;
12
+ xmlNodePtr node;
13
+ VALUE document;
14
+ VALUE name;
15
+ VALUE rest;
16
+ VALUE rb_node;
17
+
18
+ rb_scan_args(argc, argv, "2*", &document, &name, &rest);
19
+
20
+ Data_Get_Struct(document, xmlDoc, xml_doc);
21
+
22
+ node = xmlNewReference(
23
+ xml_doc,
24
+ (const xmlChar *)StringValuePtr(name)
25
+ );
26
+
27
+ NOKOGIRI_ROOT_NODE(node);
28
+
29
+ rb_node = Nokogiri_wrap_xml_node(klass, node);
30
+ rb_obj_call_init(rb_node, argc, argv);
31
+
32
+ if(rb_block_given_p()) rb_yield(rb_node);
33
+
34
+ return rb_node;
35
+ }
36
+
37
+ VALUE cNokogiriXmlEntityReference;
38
+ void init_xml_entity_reference()
39
+ {
40
+ VALUE nokogiri = rb_define_module("Nokogiri");
41
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
42
+ VALUE node = rb_define_class_under(xml, "Node", rb_cObject);
43
+
44
+ /*
45
+ * EntityReference represents an EntityReference node in an xml document.
46
+ */
47
+ VALUE klass = rb_define_class_under(xml, "EntityReference", node);
48
+
49
+ cNokogiriXmlEntityReference = klass;
50
+
51
+ rb_define_singleton_method(klass, "new", new, -1);
52
+ }
@@ -0,0 +1,9 @@
1
+ #ifndef NOKOGIRI_XML_ENTITY_REFERENCE
2
+ #define NOKOGIRI_XML_ENTITY_REFERENCE
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_entity_reference();
7
+
8
+ extern VALUE cNokogiriXmlEntityReference;
9
+ #endif
@@ -0,0 +1,31 @@
1
+ #include <xml_io.h>
2
+
3
+ static ID id_read, id_write;
4
+
5
+ int io_read_callback(void * ctx, char * buffer, int len) {
6
+ VALUE io = (VALUE)ctx;
7
+ VALUE string = rb_funcall(io, id_read, 1, INT2NUM(len));
8
+
9
+ if(NIL_P(string)) return 0;
10
+
11
+ memcpy(buffer, StringValuePtr(string), (unsigned int)RSTRING_LEN(string));
12
+
13
+ return (int)RSTRING_LEN(string);
14
+ }
15
+
16
+ int io_write_callback(void * ctx, char * buffer, int len) {
17
+ VALUE io = (VALUE)ctx;
18
+ VALUE string = rb_str_new(buffer, len);
19
+
20
+ rb_funcall(io, id_write, 1, string);
21
+ return len;
22
+ }
23
+
24
+ int io_close_callback(void * ctx) {
25
+ return 0;
26
+ }
27
+
28
+ void init_nokogiri_io() {
29
+ id_read = rb_intern("read");
30
+ id_write = rb_intern("write");
31
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef NOKOGIRI_XML_IO
2
+ #define NOKOGIRI_XML_IO
3
+
4
+ #include <nokogiri.h>
5
+
6
+ int io_read_callback(void * ctx, char * buffer, int len);
7
+ int io_write_callback(void * ctx, char * buffer, int len);
8
+ int io_close_callback(void * ctx);
9
+ void init_nokogiri_io();
10
+
11
+ #endif
@@ -0,0 +1,84 @@
1
+ #include <xml_namespace.h>
2
+
3
+ VALUE cNokogiriXmlNamespace ;
4
+
5
+ /*
6
+ * call-seq:
7
+ * prefix
8
+ *
9
+ * Get the prefix for this namespace. Returns +nil+ if there is no prefix.
10
+ */
11
+ static VALUE prefix(VALUE self)
12
+ {
13
+ xmlNsPtr ns;
14
+ xmlDocPtr doc;
15
+
16
+ Data_Get_Struct(self, xmlNs, ns);
17
+ if(!ns->prefix) return Qnil;
18
+
19
+ Data_Get_Struct(rb_iv_get(self, "@document"), xmlDoc, doc);
20
+
21
+ return NOKOGIRI_STR_NEW2(ns->prefix);
22
+ }
23
+
24
+ /*
25
+ * call-seq:
26
+ * href
27
+ *
28
+ * Get the href for this namespace
29
+ */
30
+ static VALUE href(VALUE self)
31
+ {
32
+ xmlNsPtr ns;
33
+ xmlDocPtr doc;
34
+
35
+ Data_Get_Struct(self, xmlNs, ns);
36
+ if(!ns->href) return Qnil;
37
+
38
+ Data_Get_Struct(rb_iv_get(self, "@document"), xmlDoc, doc);
39
+
40
+ return NOKOGIRI_STR_NEW2(ns->href);
41
+ }
42
+
43
+ VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
44
+ {
45
+ VALUE ns, document, node_cache;
46
+
47
+ assert(doc->_private);
48
+
49
+ if(node->_private)
50
+ return (VALUE)node->_private;
51
+
52
+ ns = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, node);
53
+
54
+ document = DOC_RUBY_OBJECT(doc);
55
+
56
+ node_cache = rb_iv_get(document, "@node_cache");
57
+ rb_ary_push(node_cache, ns);
58
+
59
+ rb_iv_set(ns, "@document", DOC_RUBY_OBJECT(doc));
60
+
61
+ node->_private = (void *)ns;
62
+
63
+ return ns;
64
+ }
65
+
66
+ VALUE Nokogiri_wrap_xml_namespace2(VALUE document, xmlNsPtr node)
67
+ {
68
+ xmlDocPtr doc;
69
+ Data_Get_Struct(document, xmlDoc, doc) ;
70
+ return Nokogiri_wrap_xml_namespace(doc, node);
71
+ }
72
+
73
+
74
+ void init_xml_namespace()
75
+ {
76
+ VALUE nokogiri = rb_define_module("Nokogiri");
77
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
78
+ VALUE klass = rb_define_class_under(xml, "Namespace", rb_cObject);
79
+
80
+ cNokogiriXmlNamespace = klass;
81
+
82
+ rb_define_method(klass, "prefix", prefix, 0);
83
+ rb_define_method(klass, "href", href, 0);
84
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef NOKOGIRI_XML_NAMESPACE
2
+ #define NOKOGIRI_XML_NAMESPACE
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_namespace();
7
+
8
+ extern VALUE cNokogiriXmlNamespace ;
9
+
10
+ VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node) ;
11
+ VALUE Nokogiri_wrap_xml_namespace2(VALUE document, xmlNsPtr node) ;
12
+
13
+ #endif
@@ -0,0 +1,1347 @@
1
+ #include <xml_node.h>
2
+
3
+ static ID decorate, decorate_bang;
4
+
5
+ #ifdef DEBUG
6
+ static void debug_node_dealloc(xmlNodePtr x)
7
+ {
8
+ NOKOGIRI_DEBUG_START(x)
9
+ NOKOGIRI_DEBUG_END(x)
10
+ }
11
+ #else
12
+ # define debug_node_dealloc 0
13
+ #endif
14
+
15
+ static void mark(xmlNodePtr node)
16
+ {
17
+ /* it's OK if the document isn't fully realized (as in XML::Reader). */
18
+ /* see http://github.com/tenderlove/nokogiri/issues/closed/#issue/95 */
19
+ if (DOC_RUBY_OBJECT_TEST(node->doc) && DOC_RUBY_OBJECT(node->doc))
20
+ rb_gc_mark(DOC_RUBY_OBJECT(node->doc));
21
+ }
22
+
23
+ /* :nodoc: */
24
+ typedef xmlNodePtr (*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
25
+
26
+ /* :nodoc: */
27
+ static void relink_namespace(xmlNodePtr reparented)
28
+ {
29
+ xmlNodePtr child;
30
+
31
+ /* Avoid segv when relinking against unlinked nodes. */
32
+ if(!reparented->parent) return;
33
+
34
+ /* Make sure that our reparented node has the correct namespaces */
35
+ if(!reparented->ns && reparented->doc != (xmlDocPtr)reparented->parent)
36
+ xmlSetNs(reparented, reparented->parent->ns);
37
+
38
+ /* Search our parents for an existing definition */
39
+ if(reparented->nsDef) {
40
+ xmlNsPtr curr = reparented->nsDef;
41
+ xmlNsPtr prev = NULL;
42
+
43
+ while(curr) {
44
+ xmlNsPtr ns = xmlSearchNsByHref(
45
+ reparented->doc,
46
+ reparented->parent,
47
+ curr->href
48
+ );
49
+ /* If we find the namespace is already declared, remove it from this
50
+ * definition list. */
51
+ if(ns && ns != curr) {
52
+ if (prev) {
53
+ prev->next = curr->next;
54
+ } else {
55
+ reparented->nsDef = curr->next;
56
+ }
57
+ NOKOGIRI_ROOT_NSDEF(curr, reparented->doc);
58
+ } else {
59
+ prev = curr;
60
+ }
61
+ curr = curr->next;
62
+ }
63
+ }
64
+
65
+ /* Only walk all children if there actually is a namespace we need to */
66
+ /* reparent. */
67
+ if(NULL == reparented->ns) return;
68
+
69
+ /* When a node gets reparented, walk it's children to make sure that */
70
+ /* their namespaces are reparented as well. */
71
+ child = reparented->children;
72
+ while(NULL != child) {
73
+ relink_namespace(child);
74
+ child = child->next;
75
+ }
76
+ }
77
+
78
+ /* :nodoc: */
79
+ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
80
+ {
81
+ xmlNodePtr retval ;
82
+
83
+ retval = xmlReplaceNode(pivot, new_node) ;
84
+
85
+ if (retval == pivot) {
86
+ retval = new_node ; /* return semantics for reparent_node_with */
87
+ }
88
+
89
+ /* work around libxml2 issue: https://bugzilla.gnome.org/show_bug.cgi?id=615612 */
90
+ if (retval->type == XML_TEXT_NODE) {
91
+ if (retval->prev && retval->prev->type == XML_TEXT_NODE) {
92
+ retval = xmlTextMerge(retval->prev, retval);
93
+ }
94
+ if (retval->next && retval->next->type == XML_TEXT_NODE) {
95
+ retval = xmlTextMerge(retval, retval->next);
96
+ }
97
+ }
98
+
99
+ return retval ;
100
+ }
101
+
102
+ /* :nodoc: */
103
+ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
104
+ {
105
+ VALUE reparented_obj ;
106
+ xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text ;
107
+
108
+ if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode))
109
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
110
+ if(rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument))
111
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
112
+
113
+ Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
114
+ Data_Get_Struct(pivot_obj, xmlNode, pivot);
115
+
116
+ if(XML_DOCUMENT_NODE == reparentee->type || XML_HTML_DOCUMENT_NODE == reparentee->type)
117
+ rb_raise(rb_eArgError, "cannot reparent a document node");
118
+
119
+ xmlUnlinkNode(reparentee);
120
+
121
+ if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
122
+ /*
123
+ * if the reparentee is a text node, there's a very good chance it will be
124
+ * merged with an adjacent text node after being reparented, and in that case
125
+ * libxml will free the underlying C struct.
126
+ *
127
+ * since we clearly have a ruby object which references the underlying
128
+ * memory, we can't let the C struct get freed. let's pickle the original
129
+ * reparentee by rooting it; and then we'll reparent a duplicate of the
130
+ * node that we don't care about preserving.
131
+ *
132
+ * alternatively, if the reparentee is from a different document than the
133
+ * pivot node, libxml2 is going to get confused about which document's
134
+ * "dictionary" the node's strings belong to (this is an otherwise
135
+ * uninteresting libxml2 implementation detail). as a result, we cannot
136
+ * reparent the actual reparentee, so we reparent a duplicate.
137
+ */
138
+ NOKOGIRI_ROOT_NODE(reparentee);
139
+ if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
140
+ rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
141
+ }
142
+ }
143
+
144
+ if (reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
145
+ /*
146
+ * libxml merges text nodes in a right-to-left fashion, meaning that if
147
+ * there are two text nodes who would be adjacent, the right (or following,
148
+ * or next) node will be merged into the left (or preceding, or previous)
149
+ * node.
150
+ *
151
+ * and by "merged" I mean the string contents will be concatenated onto the
152
+ * left node's contents, and then the node will be freed.
153
+ *
154
+ * which means that if we have a ruby object wrapped around the right node,
155
+ * its memory would be freed out from under it.
156
+ *
157
+ * so, we detect this edge case and unlink-and-root the text node before it gets
158
+ * merged. then we dup the node and insert that duplicate back into the
159
+ * document where the real node was.
160
+ *
161
+ * yes, this is totally lame.
162
+ */
163
+ next_text = pivot->next ;
164
+ new_next_text = xmlDocCopyNode(next_text, pivot->doc, 1) ;
165
+
166
+ xmlUnlinkNode(next_text);
167
+ NOKOGIRI_ROOT_NODE(next_text);
168
+
169
+ xmlAddNextSibling(pivot, new_next_text);
170
+ }
171
+
172
+ /* TODO: I really want to remove this. We shouldn't support 2.6.16 anymore */
173
+ if ( reparentee->type == XML_TEXT_NODE && pivot->type == XML_TEXT_NODE && is_2_6_16() ) {
174
+ /* work around a string-handling bug in libxml 2.6.16. we'd rather leak than segfault. */
175
+ pivot->content = xmlStrdup(pivot->content);
176
+ }
177
+
178
+ if(!(reparented = (*prf)(pivot, reparentee))) {
179
+ rb_raise(rb_eRuntimeError, "Could not reparent node");
180
+ }
181
+
182
+ /*
183
+ * make sure the ruby object is pointed at the just-reparented node, which
184
+ * might be a duplicate (see above) or might be the result of merging
185
+ * adjacent text nodes.
186
+ */
187
+ DATA_PTR(reparentee_obj) = reparented ;
188
+
189
+ relink_namespace(reparented);
190
+
191
+ reparented_obj = Nokogiri_wrap_xml_node(Qnil, reparented);
192
+
193
+ rb_funcall(reparented_obj, decorate_bang, 0);
194
+
195
+ return reparented_obj ;
196
+ }
197
+
198
+
199
+ /*
200
+ * call-seq:
201
+ * document
202
+ *
203
+ * Get the document for this Node
204
+ */
205
+ static VALUE document(VALUE self)
206
+ {
207
+ xmlNodePtr node;
208
+ Data_Get_Struct(self, xmlNode, node);
209
+ return DOC_RUBY_OBJECT(node->doc);
210
+ }
211
+
212
+ /*
213
+ * call-seq:
214
+ * pointer_id
215
+ *
216
+ * Get the internal pointer number
217
+ */
218
+ static VALUE pointer_id(VALUE self)
219
+ {
220
+ xmlNodePtr node;
221
+ Data_Get_Struct(self, xmlNode, node);
222
+
223
+ return INT2NUM((long)(node));
224
+ }
225
+
226
+ /*
227
+ * call-seq:
228
+ * encode_special_chars(string)
229
+ *
230
+ * Encode any special characters in +string+
231
+ */
232
+ static VALUE encode_special_chars(VALUE self, VALUE string)
233
+ {
234
+ xmlNodePtr node;
235
+ xmlChar *encoded;
236
+ VALUE encoded_str;
237
+
238
+ Data_Get_Struct(self, xmlNode, node);
239
+ encoded = xmlEncodeSpecialChars(
240
+ node->doc,
241
+ (const xmlChar *)StringValuePtr(string)
242
+ );
243
+
244
+ encoded_str = NOKOGIRI_STR_NEW2(encoded);
245
+ xmlFree(encoded);
246
+
247
+ return encoded_str;
248
+ }
249
+
250
+ /*
251
+ * call-seq:
252
+ * create_internal_subset(name, external_id, system_id)
253
+ *
254
+ * Create an internal subset
255
+ */
256
+ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
257
+ {
258
+ xmlNodePtr node;
259
+ xmlDocPtr doc;
260
+ xmlDtdPtr dtd;
261
+
262
+ Data_Get_Struct(self, xmlNode, node);
263
+
264
+ doc = node->doc;
265
+
266
+ if(xmlGetIntSubset(doc))
267
+ rb_raise(rb_eRuntimeError, "Document already has an internal subset");
268
+
269
+ dtd = xmlCreateIntSubset(
270
+ doc,
271
+ NIL_P(name) ? NULL : (const xmlChar *)StringValuePtr(name),
272
+ NIL_P(external_id) ? NULL : (const xmlChar *)StringValuePtr(external_id),
273
+ NIL_P(system_id) ? NULL : (const xmlChar *)StringValuePtr(system_id)
274
+ );
275
+
276
+ if(!dtd) return Qnil;
277
+
278
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
279
+ }
280
+
281
+ /*
282
+ * call-seq:
283
+ * create_external_subset(name, external_id, system_id)
284
+ *
285
+ * Create an external subset
286
+ */
287
+ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
288
+ {
289
+ xmlNodePtr node;
290
+ xmlDocPtr doc;
291
+ xmlDtdPtr dtd;
292
+
293
+ Data_Get_Struct(self, xmlNode, node);
294
+
295
+ doc = node->doc;
296
+
297
+ if(doc->extSubset)
298
+ rb_raise(rb_eRuntimeError, "Document already has an external subset");
299
+
300
+ dtd = xmlNewDtd(
301
+ doc,
302
+ NIL_P(name) ? NULL : (const xmlChar *)StringValuePtr(name),
303
+ NIL_P(external_id) ? NULL : (const xmlChar *)StringValuePtr(external_id),
304
+ NIL_P(system_id) ? NULL : (const xmlChar *)StringValuePtr(system_id)
305
+ );
306
+
307
+ if(!dtd) return Qnil;
308
+
309
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
310
+ }
311
+
312
+ /*
313
+ * call-seq:
314
+ * external_subset
315
+ *
316
+ * Get the external subset
317
+ */
318
+ static VALUE external_subset(VALUE self)
319
+ {
320
+ xmlNodePtr node;
321
+ xmlDocPtr doc;
322
+ xmlDtdPtr dtd;
323
+
324
+ Data_Get_Struct(self, xmlNode, node);
325
+
326
+ if(!node->doc) return Qnil;
327
+
328
+ doc = node->doc;
329
+ dtd = doc->extSubset;
330
+
331
+ if(!dtd) return Qnil;
332
+
333
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
334
+ }
335
+
336
+ /*
337
+ * call-seq:
338
+ * internal_subset
339
+ *
340
+ * Get the internal subset
341
+ */
342
+ static VALUE internal_subset(VALUE self)
343
+ {
344
+ xmlNodePtr node;
345
+ xmlDocPtr doc;
346
+ xmlDtdPtr dtd;
347
+
348
+ Data_Get_Struct(self, xmlNode, node);
349
+
350
+ if(!node->doc) return Qnil;
351
+
352
+ doc = node->doc;
353
+ dtd = xmlGetIntSubset(doc);
354
+
355
+ if(!dtd) return Qnil;
356
+
357
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
358
+ }
359
+
360
+ /*
361
+ * call-seq:
362
+ * dup
363
+ *
364
+ * Copy this node. An optional depth may be passed in, but it defaults
365
+ * to a deep copy. 0 is a shallow copy, 1 is a deep copy.
366
+ */
367
+ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
368
+ {
369
+ VALUE level;
370
+ xmlNodePtr node, dup;
371
+
372
+ if(rb_scan_args(argc, argv, "01", &level) == 0)
373
+ level = INT2NUM((long)1);
374
+
375
+ Data_Get_Struct(self, xmlNode, node);
376
+
377
+ dup = xmlDocCopyNode(node, node->doc, (int)NUM2INT(level));
378
+ if(dup == NULL) return Qnil;
379
+
380
+ return Nokogiri_wrap_xml_node(rb_obj_class(self), dup);
381
+ }
382
+
383
+ /*
384
+ * call-seq:
385
+ * unlink
386
+ *
387
+ * Unlink this node from its current context.
388
+ */
389
+ static VALUE unlink_node(VALUE self)
390
+ {
391
+ xmlNodePtr node;
392
+ Data_Get_Struct(self, xmlNode, node);
393
+ xmlUnlinkNode(node);
394
+ NOKOGIRI_ROOT_NODE(node);
395
+ return self;
396
+ }
397
+
398
+ /*
399
+ * call-seq:
400
+ * blank?
401
+ *
402
+ * Is this node blank?
403
+ */
404
+ static VALUE blank_eh(VALUE self)
405
+ {
406
+ xmlNodePtr node;
407
+ Data_Get_Struct(self, xmlNode, node);
408
+ return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
409
+ }
410
+
411
+ /*
412
+ * call-seq:
413
+ * next_sibling
414
+ *
415
+ * Returns the next sibling node
416
+ */
417
+ static VALUE next_sibling(VALUE self)
418
+ {
419
+ xmlNodePtr node, sibling;
420
+ Data_Get_Struct(self, xmlNode, node);
421
+
422
+ sibling = node->next;
423
+ if(!sibling) return Qnil;
424
+
425
+ return Nokogiri_wrap_xml_node(Qnil, sibling) ;
426
+ }
427
+
428
+ /*
429
+ * call-seq:
430
+ * previous_sibling
431
+ *
432
+ * Returns the previous sibling node
433
+ */
434
+ static VALUE previous_sibling(VALUE self)
435
+ {
436
+ xmlNodePtr node, sibling;
437
+ Data_Get_Struct(self, xmlNode, node);
438
+
439
+ sibling = node->prev;
440
+ if(!sibling) return Qnil;
441
+
442
+ return Nokogiri_wrap_xml_node(Qnil, sibling);
443
+ }
444
+
445
+ /*
446
+ * call-seq:
447
+ * next_element
448
+ *
449
+ * Returns the next Nokogiri::XML::Element type sibling node.
450
+ */
451
+ static VALUE next_element(VALUE self)
452
+ {
453
+ xmlNodePtr node, sibling;
454
+ Data_Get_Struct(self, xmlNode, node);
455
+
456
+ sibling = xmlNextElementSibling(node);
457
+ if(!sibling) return Qnil;
458
+
459
+ return Nokogiri_wrap_xml_node(Qnil, sibling);
460
+ }
461
+
462
+ /*
463
+ * call-seq:
464
+ * previous_element
465
+ *
466
+ * Returns the previous Nokogiri::XML::Element type sibling node.
467
+ */
468
+ static VALUE previous_element(VALUE self)
469
+ {
470
+ xmlNodePtr node, sibling;
471
+ Data_Get_Struct(self, xmlNode, node);
472
+
473
+ /*
474
+ * note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
475
+ */
476
+ sibling = node->prev;
477
+ if(!sibling) return Qnil;
478
+
479
+ while(sibling && sibling->type != XML_ELEMENT_NODE)
480
+ sibling = sibling->prev;
481
+
482
+ return sibling ? Nokogiri_wrap_xml_node(Qnil, sibling) : Qnil ;
483
+ }
484
+
485
+ /* :nodoc: */
486
+ static VALUE replace(VALUE self, VALUE new_node)
487
+ {
488
+ return reparent_node_with(self, new_node, xmlReplaceNodeWrapper) ;
489
+ }
490
+
491
+ /*
492
+ * call-seq:
493
+ * children
494
+ *
495
+ * Get the list of children for this node as a NodeSet
496
+ */
497
+ static VALUE children(VALUE self)
498
+ {
499
+ xmlNodePtr node;
500
+ xmlNodePtr child;
501
+ xmlNodeSetPtr set;
502
+ VALUE document;
503
+ VALUE node_set;
504
+
505
+ Data_Get_Struct(self, xmlNode, node);
506
+
507
+ child = node->children;
508
+ set = xmlXPathNodeSetCreate(child);
509
+
510
+ document = DOC_RUBY_OBJECT(node->doc);
511
+
512
+ if(!child) return Nokogiri_wrap_xml_node_set(set, document);
513
+
514
+ child = child->next;
515
+ while(NULL != child) {
516
+ xmlXPathNodeSetAddUnique(set, child);
517
+ child = child->next;
518
+ }
519
+
520
+ node_set = Nokogiri_wrap_xml_node_set(set, document);
521
+
522
+ return node_set;
523
+ }
524
+
525
+ /*
526
+ * call-seq:
527
+ * element_children
528
+ *
529
+ * Get the list of children for this node as a NodeSet. All nodes will be
530
+ * element nodes.
531
+ *
532
+ * Example:
533
+ *
534
+ * @doc.root.element_children.all? { |x| x.element? } # => true
535
+ */
536
+ static VALUE element_children(VALUE self)
537
+ {
538
+ xmlNodePtr node;
539
+ xmlNodePtr child;
540
+ xmlNodeSetPtr set;
541
+ VALUE document;
542
+ VALUE node_set;
543
+
544
+ Data_Get_Struct(self, xmlNode, node);
545
+
546
+ child = xmlFirstElementChild(node);
547
+ set = xmlXPathNodeSetCreate(child);
548
+
549
+ document = DOC_RUBY_OBJECT(node->doc);
550
+
551
+ if(!child) return Nokogiri_wrap_xml_node_set(set, document);
552
+
553
+ child = xmlNextElementSibling(child);
554
+ while(NULL != child) {
555
+ xmlXPathNodeSetAddUnique(set, child);
556
+ child = xmlNextElementSibling(child);
557
+ }
558
+
559
+ node_set = Nokogiri_wrap_xml_node_set(set, document);
560
+
561
+ return node_set;
562
+ }
563
+
564
+ /*
565
+ * call-seq:
566
+ * child
567
+ *
568
+ * Returns the child node
569
+ */
570
+ static VALUE child(VALUE self)
571
+ {
572
+ xmlNodePtr node, child;
573
+ Data_Get_Struct(self, xmlNode, node);
574
+
575
+ child = node->children;
576
+ if(!child) return Qnil;
577
+
578
+ return Nokogiri_wrap_xml_node(Qnil, child);
579
+ }
580
+
581
+ /*
582
+ * call-seq:
583
+ * first_element_child
584
+ *
585
+ * Returns the first child node of this node that is an element.
586
+ *
587
+ * Example:
588
+ *
589
+ * @doc.root.first_element_child.element? # => true
590
+ */
591
+ static VALUE first_element_child(VALUE self)
592
+ {
593
+ xmlNodePtr node, child;
594
+ Data_Get_Struct(self, xmlNode, node);
595
+
596
+ child = xmlFirstElementChild(node);
597
+ if(!child) return Qnil;
598
+
599
+ return Nokogiri_wrap_xml_node(Qnil, child);
600
+ }
601
+
602
+ /*
603
+ * call-seq:
604
+ * last_element_child
605
+ *
606
+ * Returns the last child node of this node that is an element.
607
+ *
608
+ * Example:
609
+ *
610
+ * @doc.root.last_element_child.element? # => true
611
+ */
612
+ static VALUE last_element_child(VALUE self)
613
+ {
614
+ xmlNodePtr node, child;
615
+ Data_Get_Struct(self, xmlNode, node);
616
+
617
+ child = xmlLastElementChild(node);
618
+ if(!child) return Qnil;
619
+
620
+ return Nokogiri_wrap_xml_node(Qnil, child);
621
+ }
622
+
623
+ /*
624
+ * call-seq:
625
+ * key?(attribute)
626
+ *
627
+ * Returns true if +attribute+ is set
628
+ */
629
+ static VALUE key_eh(VALUE self, VALUE attribute)
630
+ {
631
+ xmlNodePtr node;
632
+ Data_Get_Struct(self, xmlNode, node);
633
+ if(xmlHasProp(node, (xmlChar *)StringValuePtr(attribute)))
634
+ return Qtrue;
635
+ return Qfalse;
636
+ }
637
+
638
+ /*
639
+ * call-seq:
640
+ * namespaced_key?(attribute, namespace)
641
+ *
642
+ * Returns true if +attribute+ is set with +namespace+
643
+ */
644
+ static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
645
+ {
646
+ xmlNodePtr node;
647
+ Data_Get_Struct(self, xmlNode, node);
648
+ if(xmlHasNsProp(node, (xmlChar *)StringValuePtr(attribute),
649
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValuePtr(namespace)))
650
+ return Qtrue;
651
+ return Qfalse;
652
+ }
653
+
654
+ /*
655
+ * call-seq:
656
+ * []=(property, value)
657
+ *
658
+ * Set the +property+ to +value+
659
+ */
660
+ static VALUE set(VALUE self, VALUE property, VALUE value)
661
+ {
662
+ xmlNodePtr node;
663
+ Data_Get_Struct(self, xmlNode, node);
664
+
665
+ xmlSetProp(node, (xmlChar *)StringValuePtr(property),
666
+ (xmlChar *)StringValuePtr(value));
667
+
668
+ return value;
669
+ }
670
+
671
+ /*
672
+ * call-seq:
673
+ * get(attribute)
674
+ *
675
+ * Get the value for +attribute+
676
+ */
677
+ static VALUE get(VALUE self, VALUE attribute)
678
+ {
679
+ xmlNodePtr node;
680
+ xmlChar* propstr ;
681
+ VALUE rval ;
682
+ Data_Get_Struct(self, xmlNode, node);
683
+
684
+ if(NIL_P(attribute)) return Qnil;
685
+
686
+ propstr = xmlGetProp(node, (xmlChar *)StringValuePtr(attribute));
687
+
688
+ if(!propstr) return Qnil;
689
+
690
+ rval = NOKOGIRI_STR_NEW2(propstr);
691
+
692
+ xmlFree(propstr);
693
+ return rval ;
694
+ }
695
+
696
+ /*
697
+ * call-seq:
698
+ * set_namespace(namespace)
699
+ *
700
+ * Set the namespace to +namespace+
701
+ */
702
+ static VALUE set_namespace(VALUE self, VALUE namespace)
703
+ {
704
+ xmlNodePtr node;
705
+ xmlNsPtr ns = NULL;
706
+
707
+ Data_Get_Struct(self, xmlNode, node);
708
+
709
+ if(!NIL_P(namespace))
710
+ Data_Get_Struct(namespace, xmlNs, ns);
711
+
712
+ xmlSetNs(node, ns);
713
+
714
+ return self;
715
+ }
716
+
717
+ /*
718
+ * call-seq:
719
+ * attribute(name)
720
+ *
721
+ * Get the attribute node with +name+
722
+ */
723
+ static VALUE attr(VALUE self, VALUE name)
724
+ {
725
+ xmlNodePtr node;
726
+ xmlAttrPtr prop;
727
+ Data_Get_Struct(self, xmlNode, node);
728
+ prop = xmlHasProp(node, (xmlChar *)StringValuePtr(name));
729
+
730
+ if(! prop) return Qnil;
731
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
732
+ }
733
+
734
+ /*
735
+ * call-seq:
736
+ * attribute_with_ns(name, namespace)
737
+ *
738
+ * Get the attribute node with +name+ and +namespace+
739
+ */
740
+ static VALUE attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
741
+ {
742
+ xmlNodePtr node;
743
+ xmlAttrPtr prop;
744
+ Data_Get_Struct(self, xmlNode, node);
745
+ prop = xmlHasNsProp(node, (xmlChar *)StringValuePtr(name),
746
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValuePtr(namespace));
747
+
748
+ if(! prop) return Qnil;
749
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
750
+ }
751
+
752
+ /*
753
+ * call-seq:
754
+ * attribute_nodes()
755
+ *
756
+ * returns a list containing the Node attributes.
757
+ */
758
+ static VALUE attribute_nodes(VALUE self)
759
+ {
760
+ /* this code in the mode of xmlHasProp() */
761
+ xmlNodePtr node;
762
+ VALUE attr;
763
+
764
+ Data_Get_Struct(self, xmlNode, node);
765
+
766
+ attr = rb_ary_new();
767
+ Nokogiri_xml_node_properties(node, attr);
768
+
769
+ return attr ;
770
+ }
771
+
772
+
773
+ /*
774
+ * call-seq:
775
+ * namespace()
776
+ *
777
+ * returns the Nokogiri::XML::Namespace for the node, if one exists.
778
+ */
779
+ static VALUE namespace(VALUE self)
780
+ {
781
+ xmlNodePtr node ;
782
+ Data_Get_Struct(self, xmlNode, node);
783
+
784
+ if (node->ns)
785
+ return Nokogiri_wrap_xml_namespace(node->doc, node->ns);
786
+
787
+ return Qnil ;
788
+ }
789
+
790
+ /*
791
+ * call-seq:
792
+ * namespace_definitions()
793
+ *
794
+ * returns a list of Namespace nodes defined on _self_
795
+ */
796
+ static VALUE namespace_definitions(VALUE self)
797
+ {
798
+ /* this code in the mode of xmlHasProp() */
799
+ xmlNodePtr node ;
800
+ VALUE list;
801
+ xmlNsPtr ns;
802
+
803
+ Data_Get_Struct(self, xmlNode, node);
804
+
805
+ list = rb_ary_new();
806
+
807
+ ns = node->nsDef;
808
+
809
+ if(!ns) return list;
810
+
811
+ while(NULL != ns) {
812
+ rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns));
813
+ ns = ns->next;
814
+ }
815
+
816
+ return list;
817
+ }
818
+
819
+ /*
820
+ * call-seq:
821
+ * namespace_scopes()
822
+ *
823
+ * returns a list of Namespace nodes in scope for _self_. this is all
824
+ * namespaces defined in the node, or in any ancestor node.
825
+ */
826
+ static VALUE namespace_scopes(VALUE self)
827
+ {
828
+ xmlNodePtr node ;
829
+ VALUE list;
830
+ xmlNsPtr *ns_list;
831
+ int j;
832
+
833
+ Data_Get_Struct(self, xmlNode, node);
834
+
835
+ list = rb_ary_new();
836
+ ns_list = xmlGetNsList(node->doc, node);
837
+
838
+ if(!ns_list) return list;
839
+
840
+ for (j = 0 ; ns_list[j] != NULL ; ++j) {
841
+ rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns_list[j]));
842
+ }
843
+
844
+ xmlFree(ns_list);
845
+ return list;
846
+ }
847
+
848
+ /*
849
+ * call-seq:
850
+ * node_type
851
+ *
852
+ * Get the type for this Node
853
+ */
854
+ static VALUE node_type(VALUE self)
855
+ {
856
+ xmlNodePtr node;
857
+ Data_Get_Struct(self, xmlNode, node);
858
+ return INT2NUM((long)node->type);
859
+ }
860
+
861
+ /*
862
+ * call-seq:
863
+ * content=
864
+ *
865
+ * Set the content for this Node
866
+ */
867
+ static VALUE set_content(VALUE self, VALUE content)
868
+ {
869
+ xmlNodePtr node, child, next ;
870
+ Data_Get_Struct(self, xmlNode, node);
871
+
872
+ child = node->children;
873
+ while (NULL != child) {
874
+ next = child->next ;
875
+ xmlUnlinkNode(child) ;
876
+ NOKOGIRI_ROOT_NODE(child) ;
877
+ child = next ;
878
+ }
879
+
880
+ xmlNodeSetContent(node, (xmlChar *)StringValuePtr(content));
881
+ return content;
882
+ }
883
+
884
+ /*
885
+ * call-seq:
886
+ * content
887
+ *
888
+ * Returns the content for this Node
889
+ */
890
+ static VALUE get_content(VALUE self)
891
+ {
892
+ xmlNodePtr node;
893
+ xmlChar * content;
894
+
895
+ Data_Get_Struct(self, xmlNode, node);
896
+
897
+ content = xmlNodeGetContent(node);
898
+ if(content) {
899
+ VALUE rval = NOKOGIRI_STR_NEW2(content);
900
+ xmlFree(content);
901
+ return rval;
902
+ }
903
+ return Qnil;
904
+ }
905
+
906
+ /* :nodoc: */
907
+ static VALUE add_child(VALUE self, VALUE new_child)
908
+ {
909
+ return reparent_node_with(self, new_child, xmlAddChild);
910
+ }
911
+
912
+ /*
913
+ * call-seq:
914
+ * parent
915
+ *
916
+ * Get the parent Node for this Node
917
+ */
918
+ static VALUE get_parent(VALUE self)
919
+ {
920
+ xmlNodePtr node, parent;
921
+ Data_Get_Struct(self, xmlNode, node);
922
+
923
+ parent = node->parent;
924
+ if(!parent) return Qnil;
925
+
926
+ return Nokogiri_wrap_xml_node(Qnil, parent) ;
927
+ }
928
+
929
+ /*
930
+ * call-seq:
931
+ * name=(new_name)
932
+ *
933
+ * Set the name for this Node
934
+ */
935
+ static VALUE set_name(VALUE self, VALUE new_name)
936
+ {
937
+ xmlNodePtr node;
938
+ Data_Get_Struct(self, xmlNode, node);
939
+ xmlNodeSetName(node, (xmlChar*)StringValuePtr(new_name));
940
+ return new_name;
941
+ }
942
+
943
+ /*
944
+ * call-seq:
945
+ * name
946
+ *
947
+ * Returns the name for this Node
948
+ */
949
+ static VALUE get_name(VALUE self)
950
+ {
951
+ xmlNodePtr node;
952
+ Data_Get_Struct(self, xmlNode, node);
953
+ if(node->name)
954
+ return NOKOGIRI_STR_NEW2(node->name);
955
+ return Qnil;
956
+ }
957
+
958
+ /*
959
+ * call-seq:
960
+ * path
961
+ *
962
+ * Returns the path associated with this Node
963
+ */
964
+ static VALUE path(VALUE self)
965
+ {
966
+ xmlNodePtr node;
967
+ xmlChar *path ;
968
+ VALUE rval;
969
+
970
+ Data_Get_Struct(self, xmlNode, node);
971
+
972
+ path = xmlGetNodePath(node);
973
+ rval = NOKOGIRI_STR_NEW2(path);
974
+ xmlFree(path);
975
+ return rval ;
976
+ }
977
+
978
+ /* :nodoc: */
979
+ static VALUE add_next_sibling(VALUE self, VALUE new_sibling)
980
+ {
981
+ return reparent_node_with(self, new_sibling, xmlAddNextSibling) ;
982
+ }
983
+
984
+ /* :nodoc: */
985
+ static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
986
+ {
987
+ return reparent_node_with(self, new_sibling, xmlAddPrevSibling) ;
988
+ }
989
+
990
+ /*
991
+ * call-seq:
992
+ * native_write_to(io, encoding, options)
993
+ *
994
+ * Write this Node to +io+ with +encoding+ and +options+
995
+ */
996
+ static VALUE native_write_to(
997
+ VALUE self,
998
+ VALUE io,
999
+ VALUE encoding,
1000
+ VALUE indent_string,
1001
+ VALUE options
1002
+ ) {
1003
+ xmlNodePtr node;
1004
+ const char * before_indent;
1005
+ xmlSaveCtxtPtr savectx;
1006
+
1007
+ Data_Get_Struct(self, xmlNode, node);
1008
+
1009
+ xmlIndentTreeOutput = 1;
1010
+
1011
+ before_indent = xmlTreeIndentString;
1012
+
1013
+ xmlTreeIndentString = StringValuePtr(indent_string);
1014
+
1015
+ savectx = xmlSaveToIO(
1016
+ (xmlOutputWriteCallback)io_write_callback,
1017
+ (xmlOutputCloseCallback)io_close_callback,
1018
+ (void *)io,
1019
+ RTEST(encoding) ? StringValuePtr(encoding) : NULL,
1020
+ (int)NUM2INT(options)
1021
+ );
1022
+
1023
+ xmlSaveTree(savectx, node);
1024
+ xmlSaveClose(savectx);
1025
+
1026
+ xmlTreeIndentString = before_indent;
1027
+ return io;
1028
+ }
1029
+
1030
+ /*
1031
+ * call-seq:
1032
+ * line
1033
+ *
1034
+ * Returns the line for this Node
1035
+ */
1036
+ static VALUE line(VALUE self)
1037
+ {
1038
+ xmlNodePtr node;
1039
+ Data_Get_Struct(self, xmlNode, node);
1040
+
1041
+ return INT2NUM(xmlGetLineNo(node));
1042
+ }
1043
+
1044
+ /*
1045
+ * call-seq:
1046
+ * add_namespace_definition(prefix, href)
1047
+ *
1048
+ * Adds a namespace definition with +prefix+ using +href+
1049
+ */
1050
+ static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
1051
+ {
1052
+ xmlNodePtr node;
1053
+ xmlNsPtr ns;
1054
+
1055
+ Data_Get_Struct(self, xmlNode, node);
1056
+
1057
+ ns = xmlNewNs(
1058
+ node,
1059
+ (const xmlChar *)StringValuePtr(href),
1060
+ (const xmlChar *)(NIL_P(prefix) ? NULL : StringValuePtr(prefix))
1061
+ );
1062
+
1063
+ if(!ns) {
1064
+ ns = xmlSearchNs(
1065
+ node->doc,
1066
+ node,
1067
+ (const xmlChar *)(NIL_P(prefix) ? NULL : StringValuePtr(prefix))
1068
+ );
1069
+ }
1070
+
1071
+ if(NIL_P(prefix)) xmlSetNs(node, ns);
1072
+
1073
+ return Nokogiri_wrap_xml_namespace(node->doc, ns);
1074
+ }
1075
+
1076
+ /*
1077
+ * call-seq:
1078
+ * new(name, document)
1079
+ *
1080
+ * Create a new node with +name+ sharing GC lifecycle with +document+
1081
+ */
1082
+ static VALUE new(int argc, VALUE *argv, VALUE klass)
1083
+ {
1084
+ xmlDocPtr doc;
1085
+ xmlNodePtr node;
1086
+ VALUE name;
1087
+ VALUE document;
1088
+ VALUE rest;
1089
+ VALUE rb_node;
1090
+
1091
+ rb_scan_args(argc, argv, "2*", &name, &document, &rest);
1092
+
1093
+ Data_Get_Struct(document, xmlDoc, doc);
1094
+
1095
+ node = xmlNewNode(NULL, (xmlChar *)StringValuePtr(name));
1096
+ node->doc = doc->doc;
1097
+ NOKOGIRI_ROOT_NODE(node);
1098
+
1099
+ rb_node = Nokogiri_wrap_xml_node(
1100
+ klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1101
+ node
1102
+ );
1103
+ rb_obj_call_init(rb_node, argc, argv);
1104
+
1105
+ if(rb_block_given_p()) rb_yield(rb_node);
1106
+
1107
+ return rb_node;
1108
+ }
1109
+
1110
+ /*
1111
+ * call-seq:
1112
+ * dump_html
1113
+ *
1114
+ * Returns the Node as html.
1115
+ */
1116
+ static VALUE dump_html(VALUE self)
1117
+ {
1118
+ xmlBufferPtr buf ;
1119
+ xmlNodePtr node ;
1120
+ VALUE html;
1121
+
1122
+ Data_Get_Struct(self, xmlNode, node);
1123
+
1124
+ buf = xmlBufferCreate() ;
1125
+ htmlNodeDump(buf, node->doc, node);
1126
+ html = NOKOGIRI_STR_NEW2(buf->content);
1127
+ xmlBufferFree(buf);
1128
+ return html ;
1129
+ }
1130
+
1131
+ /*
1132
+ * call-seq:
1133
+ * compare(other)
1134
+ *
1135
+ * Compare this Node to +other+ with respect to their Document
1136
+ */
1137
+ static VALUE compare(VALUE self, VALUE _other)
1138
+ {
1139
+ xmlNodePtr node, other;
1140
+ Data_Get_Struct(self, xmlNode, node);
1141
+ Data_Get_Struct(_other, xmlNode, other);
1142
+
1143
+ return INT2NUM((long)xmlXPathCmpNodes(other, node));
1144
+ }
1145
+
1146
+
1147
+ /* TODO: DOCUMENT ME */
1148
+ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1149
+ {
1150
+ xmlNodePtr node;
1151
+ xmlNodePtr list;
1152
+ xmlNodeSetPtr set;
1153
+ VALUE doc, err;
1154
+
1155
+ Data_Get_Struct(self, xmlNode, node);
1156
+
1157
+ if(!node->parent)
1158
+ rb_raise(rb_eRuntimeError, "no contextual parsing on unlinked nodes");
1159
+
1160
+ doc = DOC_RUBY_OBJECT(node->doc);
1161
+ err = rb_iv_get(doc, "@errors");
1162
+
1163
+ xmlSetStructuredErrorFunc((void *)err, Nokogiri_error_array_pusher);
1164
+
1165
+ /* Twiddle global variable because of a bug in libxml2.
1166
+ * http://git.gnome.org/browse/libxml2/commit/?id=e20fb5a72c83cbfc8e4a8aa3943c6be8febadab7
1167
+ */
1168
+ #ifndef HTML_PARSE_NOIMPLIED
1169
+ htmlHandleOmittedElem(0);
1170
+ #endif
1171
+
1172
+ xmlParseInNodeContext(
1173
+ node,
1174
+ StringValuePtr(_str),
1175
+ (int)RSTRING_LEN(_str),
1176
+ (int)NUM2INT(_options),
1177
+ &list);
1178
+
1179
+ #ifndef HTML_PARSE_NOIMPLIED
1180
+ htmlHandleOmittedElem(1);
1181
+ #endif
1182
+
1183
+ xmlSetStructuredErrorFunc(NULL, NULL);
1184
+
1185
+ set = xmlXPathNodeSetCreate(NULL);
1186
+
1187
+ while(list) {
1188
+ xmlXPathNodeSetAddUnique(set, list);
1189
+ list = list->next;
1190
+ }
1191
+
1192
+ return Nokogiri_wrap_xml_node_set(set, doc);
1193
+ }
1194
+
1195
+
1196
+ VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node)
1197
+ {
1198
+ VALUE document = Qnil ;
1199
+ VALUE node_cache = Qnil ;
1200
+ VALUE rb_node = Qnil ;
1201
+
1202
+ assert(node);
1203
+
1204
+ if(node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE)
1205
+ return DOC_RUBY_OBJECT(node->doc);
1206
+
1207
+ if(NULL != node->_private) return (VALUE)node->_private;
1208
+
1209
+ if(RTEST(klass))
1210
+ rb_node = Data_Wrap_Struct(klass, mark, debug_node_dealloc, node) ;
1211
+
1212
+ else switch(node->type)
1213
+ {
1214
+ case XML_ELEMENT_NODE:
1215
+ klass = cNokogiriXmlElement;
1216
+ break;
1217
+ case XML_TEXT_NODE:
1218
+ klass = cNokogiriXmlText;
1219
+ break;
1220
+ case XML_ATTRIBUTE_NODE:
1221
+ klass = cNokogiriXmlAttr;
1222
+ break;
1223
+ case XML_ENTITY_REF_NODE:
1224
+ klass = cNokogiriXmlEntityReference;
1225
+ break;
1226
+ case XML_COMMENT_NODE:
1227
+ klass = cNokogiriXmlComment;
1228
+ break;
1229
+ case XML_DOCUMENT_FRAG_NODE:
1230
+ klass = cNokogiriXmlDocumentFragment;
1231
+ break;
1232
+ case XML_PI_NODE:
1233
+ klass = cNokogiriXmlProcessingInstruction;
1234
+ break;
1235
+ case XML_ENTITY_DECL:
1236
+ klass = cNokogiriXmlEntityDecl;
1237
+ break;
1238
+ case XML_CDATA_SECTION_NODE:
1239
+ klass = cNokogiriXmlCData;
1240
+ break;
1241
+ case XML_DTD_NODE:
1242
+ klass = cNokogiriXmlDtd;
1243
+ break;
1244
+ case XML_ATTRIBUTE_DECL:
1245
+ klass = cNokogiriXmlAttributeDecl;
1246
+ break;
1247
+ case XML_ELEMENT_DECL:
1248
+ klass = cNokogiriXmlElementDecl;
1249
+ break;
1250
+ default:
1251
+ klass = cNokogiriXmlNode;
1252
+ }
1253
+
1254
+ rb_node = Data_Wrap_Struct(klass, mark, debug_node_dealloc, node) ;
1255
+
1256
+ node->_private = (void *)rb_node;
1257
+
1258
+ if (DOC_RUBY_OBJECT_TEST(node->doc) && DOC_RUBY_OBJECT(node->doc)) {
1259
+ /* it's OK if the document isn't fully realized (as in XML::Reader). */
1260
+ /* see http://github.com/tenderlove/nokogiri/issues/closed/#issue/95 */
1261
+ document = DOC_RUBY_OBJECT(node->doc);
1262
+ node_cache = DOC_NODE_CACHE(node->doc);
1263
+ rb_ary_push(node_cache, rb_node);
1264
+ rb_funcall(document, decorate, 1, rb_node);
1265
+ }
1266
+
1267
+ return rb_node ;
1268
+ }
1269
+
1270
+
1271
+ void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_list)
1272
+ {
1273
+ xmlAttrPtr prop;
1274
+ prop = node->properties ;
1275
+ while (prop != NULL) {
1276
+ rb_ary_push(attr_list, Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop));
1277
+ prop = prop->next ;
1278
+ }
1279
+ }
1280
+
1281
+ VALUE cNokogiriXmlNode ;
1282
+ VALUE cNokogiriXmlElement ;
1283
+
1284
+ void init_xml_node()
1285
+ {
1286
+ VALUE nokogiri = rb_define_module("Nokogiri");
1287
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
1288
+ VALUE klass = rb_define_class_under(xml, "Node", rb_cObject);
1289
+
1290
+ cNokogiriXmlNode = klass;
1291
+
1292
+ cNokogiriXmlElement = rb_define_class_under(xml, "Element", klass);
1293
+
1294
+ rb_define_singleton_method(klass, "new", new, -1);
1295
+
1296
+ rb_define_method(klass, "add_namespace_definition", add_namespace_definition, 2);
1297
+ rb_define_method(klass, "node_name", get_name, 0);
1298
+ rb_define_method(klass, "document", document, 0);
1299
+ rb_define_method(klass, "node_name=", set_name, 1);
1300
+ rb_define_method(klass, "parent", get_parent, 0);
1301
+ rb_define_method(klass, "child", child, 0);
1302
+ rb_define_method(klass, "first_element_child", first_element_child, 0);
1303
+ rb_define_method(klass, "last_element_child", last_element_child, 0);
1304
+ rb_define_method(klass, "children", children, 0);
1305
+ rb_define_method(klass, "element_children", element_children, 0);
1306
+ rb_define_method(klass, "next_sibling", next_sibling, 0);
1307
+ rb_define_method(klass, "previous_sibling", previous_sibling, 0);
1308
+ rb_define_method(klass, "next_element", next_element, 0);
1309
+ rb_define_method(klass, "previous_element", previous_element, 0);
1310
+ rb_define_method(klass, "node_type", node_type, 0);
1311
+ rb_define_method(klass, "content", get_content, 0);
1312
+ rb_define_method(klass, "path", path, 0);
1313
+ rb_define_method(klass, "key?", key_eh, 1);
1314
+ rb_define_method(klass, "namespaced_key?", namespaced_key_eh, 2);
1315
+ rb_define_method(klass, "blank?", blank_eh, 0);
1316
+ rb_define_method(klass, "[]=", set, 2);
1317
+ rb_define_method(klass, "attribute_nodes", attribute_nodes, 0);
1318
+ rb_define_method(klass, "attribute", attr, 1);
1319
+ rb_define_method(klass, "attribute_with_ns", attribute_with_ns, 2);
1320
+ rb_define_method(klass, "namespace", namespace, 0);
1321
+ rb_define_method(klass, "namespace_definitions", namespace_definitions, 0);
1322
+ rb_define_method(klass, "namespace_scopes", namespace_scopes, 0);
1323
+ rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
1324
+ rb_define_method(klass, "dup", duplicate_node, -1);
1325
+ rb_define_method(klass, "unlink", unlink_node, 0);
1326
+ rb_define_method(klass, "internal_subset", internal_subset, 0);
1327
+ rb_define_method(klass, "external_subset", external_subset, 0);
1328
+ rb_define_method(klass, "create_internal_subset", create_internal_subset, 3);
1329
+ rb_define_method(klass, "create_external_subset", create_external_subset, 3);
1330
+ rb_define_method(klass, "pointer_id", pointer_id, 0);
1331
+ rb_define_method(klass, "line", line, 0);
1332
+
1333
+ rb_define_private_method(klass, "in_context", in_context, 2);
1334
+ rb_define_private_method(klass, "add_child_node", add_child, 1);
1335
+ rb_define_private_method(klass, "add_previous_sibling_node", add_previous_sibling, 1);
1336
+ rb_define_private_method(klass, "add_next_sibling_node", add_next_sibling, 1);
1337
+ rb_define_private_method(klass, "replace_node", replace, 1);
1338
+ rb_define_private_method(klass, "dump_html", dump_html, 0);
1339
+ rb_define_private_method(klass, "native_write_to", native_write_to, 4);
1340
+ rb_define_private_method(klass, "native_content=", set_content, 1);
1341
+ rb_define_private_method(klass, "get", get, 1);
1342
+ rb_define_private_method(klass, "set_namespace", set_namespace, 1);
1343
+ rb_define_private_method(klass, "compare", compare, 1);
1344
+
1345
+ decorate = rb_intern("decorate");
1346
+ decorate_bang = rb_intern("decorate!");
1347
+ }