nokogiri 1.10.3 → 1.13.9

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 (220) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/LICENSE-DEPENDENCIES.md +1173 -884
  4. data/LICENSE.md +1 -1
  5. data/README.md +178 -96
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +13 -62
  8. data/ext/nokogiri/depend +38 -358
  9. data/ext/nokogiri/extconf.rb +761 -424
  10. data/ext/nokogiri/gumbo.c +584 -0
  11. data/ext/nokogiri/html4_document.c +166 -0
  12. data/ext/nokogiri/html4_element_description.c +294 -0
  13. data/ext/nokogiri/html4_entity_lookup.c +37 -0
  14. data/ext/nokogiri/html4_sax_parser_context.c +119 -0
  15. data/ext/nokogiri/html4_sax_push_parser.c +95 -0
  16. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  17. data/ext/nokogiri/nokogiri.c +228 -91
  18. data/ext/nokogiri/nokogiri.h +199 -88
  19. data/ext/nokogiri/test_global_handlers.c +40 -0
  20. data/ext/nokogiri/xml_attr.c +17 -17
  21. data/ext/nokogiri/xml_attribute_decl.c +21 -21
  22. data/ext/nokogiri/xml_cdata.c +14 -19
  23. data/ext/nokogiri/xml_comment.c +19 -26
  24. data/ext/nokogiri/xml_document.c +296 -220
  25. data/ext/nokogiri/xml_document_fragment.c +12 -16
  26. data/ext/nokogiri/xml_dtd.c +64 -58
  27. data/ext/nokogiri/xml_element_content.c +31 -26
  28. data/ext/nokogiri/xml_element_decl.c +25 -25
  29. data/ext/nokogiri/xml_encoding_handler.c +43 -18
  30. data/ext/nokogiri/xml_entity_decl.c +37 -35
  31. data/ext/nokogiri/xml_entity_reference.c +16 -18
  32. data/ext/nokogiri/xml_namespace.c +98 -53
  33. data/ext/nokogiri/xml_node.c +1065 -653
  34. data/ext/nokogiri/xml_node_set.c +178 -166
  35. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  36. data/ext/nokogiri/xml_reader.c +277 -175
  37. data/ext/nokogiri/xml_relax_ng.c +52 -28
  38. data/ext/nokogiri/xml_sax_parser.c +112 -112
  39. data/ext/nokogiri/xml_sax_parser_context.c +112 -86
  40. data/ext/nokogiri/xml_sax_push_parser.c +36 -27
  41. data/ext/nokogiri/xml_schema.c +114 -35
  42. data/ext/nokogiri/xml_syntax_error.c +42 -21
  43. data/ext/nokogiri/xml_text.c +14 -18
  44. data/ext/nokogiri/xml_xpath_context.c +226 -115
  45. data/ext/nokogiri/xslt_stylesheet.c +265 -173
  46. data/gumbo-parser/CHANGES.md +63 -0
  47. data/gumbo-parser/Makefile +101 -0
  48. data/gumbo-parser/THANKS +27 -0
  49. data/gumbo-parser/src/Makefile +34 -0
  50. data/gumbo-parser/src/README.md +41 -0
  51. data/gumbo-parser/src/ascii.c +75 -0
  52. data/gumbo-parser/src/ascii.h +115 -0
  53. data/gumbo-parser/src/attribute.c +42 -0
  54. data/gumbo-parser/src/attribute.h +17 -0
  55. data/gumbo-parser/src/char_ref.c +22225 -0
  56. data/gumbo-parser/src/char_ref.h +29 -0
  57. data/gumbo-parser/src/char_ref.rl +2154 -0
  58. data/gumbo-parser/src/error.c +626 -0
  59. data/gumbo-parser/src/error.h +148 -0
  60. data/gumbo-parser/src/foreign_attrs.c +104 -0
  61. data/gumbo-parser/src/foreign_attrs.gperf +27 -0
  62. data/gumbo-parser/src/gumbo.h +943 -0
  63. data/gumbo-parser/src/insertion_mode.h +33 -0
  64. data/gumbo-parser/src/macros.h +91 -0
  65. data/gumbo-parser/src/parser.c +4875 -0
  66. data/gumbo-parser/src/parser.h +41 -0
  67. data/gumbo-parser/src/replacement.h +33 -0
  68. data/gumbo-parser/src/string_buffer.c +103 -0
  69. data/gumbo-parser/src/string_buffer.h +68 -0
  70. data/gumbo-parser/src/string_piece.c +48 -0
  71. data/gumbo-parser/src/svg_attrs.c +174 -0
  72. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  73. data/gumbo-parser/src/svg_tags.c +137 -0
  74. data/gumbo-parser/src/svg_tags.gperf +55 -0
  75. data/gumbo-parser/src/tag.c +222 -0
  76. data/gumbo-parser/src/tag_lookup.c +382 -0
  77. data/gumbo-parser/src/tag_lookup.gperf +169 -0
  78. data/gumbo-parser/src/tag_lookup.h +13 -0
  79. data/gumbo-parser/src/token_buffer.c +79 -0
  80. data/gumbo-parser/src/token_buffer.h +71 -0
  81. data/gumbo-parser/src/token_type.h +17 -0
  82. data/gumbo-parser/src/tokenizer.c +3463 -0
  83. data/gumbo-parser/src/tokenizer.h +112 -0
  84. data/gumbo-parser/src/tokenizer_states.h +339 -0
  85. data/gumbo-parser/src/utf8.c +245 -0
  86. data/gumbo-parser/src/utf8.h +164 -0
  87. data/gumbo-parser/src/util.c +68 -0
  88. data/gumbo-parser/src/util.h +30 -0
  89. data/gumbo-parser/src/vector.c +111 -0
  90. data/gumbo-parser/src/vector.h +45 -0
  91. data/lib/nokogiri/class_resolver.rb +67 -0
  92. data/lib/nokogiri/css/node.rb +10 -8
  93. data/lib/nokogiri/css/parser.rb +397 -377
  94. data/lib/nokogiri/css/parser.y +250 -245
  95. data/lib/nokogiri/css/parser_extras.rb +54 -49
  96. data/lib/nokogiri/css/syntax_error.rb +3 -1
  97. data/lib/nokogiri/css/tokenizer.rb +107 -104
  98. data/lib/nokogiri/css/tokenizer.rex +3 -2
  99. data/lib/nokogiri/css/xpath_visitor.rb +218 -91
  100. data/lib/nokogiri/css.rb +50 -17
  101. data/lib/nokogiri/decorators/slop.rb +9 -7
  102. data/lib/nokogiri/extension.rb +31 -0
  103. data/lib/nokogiri/gumbo.rb +15 -0
  104. data/lib/nokogiri/html.rb +38 -27
  105. data/lib/nokogiri/{html → html4}/builder.rb +4 -2
  106. data/lib/nokogiri/{html → html4}/document.rb +103 -105
  107. data/lib/nokogiri/html4/document_fragment.rb +54 -0
  108. data/lib/nokogiri/{html → html4}/element_description.rb +3 -1
  109. data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
  110. data/lib/nokogiri/{html → html4}/entity_lookup.rb +4 -2
  111. data/lib/nokogiri/{html → html4}/sax/parser.rb +17 -16
  112. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  113. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
  114. data/lib/nokogiri/html4.rb +46 -0
  115. data/lib/nokogiri/html5/document.rb +91 -0
  116. data/lib/nokogiri/html5/document_fragment.rb +83 -0
  117. data/lib/nokogiri/html5/node.rb +100 -0
  118. data/lib/nokogiri/html5.rb +478 -0
  119. data/lib/nokogiri/jruby/dependencies.rb +21 -0
  120. data/lib/nokogiri/syntax_error.rb +2 -0
  121. data/lib/nokogiri/version/constant.rb +6 -0
  122. data/lib/nokogiri/version/info.rb +222 -0
  123. data/lib/nokogiri/version.rb +3 -108
  124. data/lib/nokogiri/xml/attr.rb +6 -3
  125. data/lib/nokogiri/xml/attribute_decl.rb +3 -1
  126. data/lib/nokogiri/xml/builder.rb +97 -53
  127. data/lib/nokogiri/xml/cdata.rb +3 -1
  128. data/lib/nokogiri/xml/character_data.rb +2 -0
  129. data/lib/nokogiri/xml/document.rb +224 -86
  130. data/lib/nokogiri/xml/document_fragment.rb +46 -44
  131. data/lib/nokogiri/xml/dtd.rb +4 -2
  132. data/lib/nokogiri/xml/element_content.rb +2 -0
  133. data/lib/nokogiri/xml/element_decl.rb +3 -1
  134. data/lib/nokogiri/xml/entity_decl.rb +4 -2
  135. data/lib/nokogiri/xml/entity_reference.rb +2 -0
  136. data/lib/nokogiri/xml/namespace.rb +3 -0
  137. data/lib/nokogiri/xml/node/save_options.rb +10 -5
  138. data/lib/nokogiri/xml/node.rb +884 -378
  139. data/lib/nokogiri/xml/node_set.rb +51 -54
  140. data/lib/nokogiri/xml/notation.rb +13 -0
  141. data/lib/nokogiri/xml/parse_options.rb +22 -8
  142. data/lib/nokogiri/xml/pp/character_data.rb +9 -6
  143. data/lib/nokogiri/xml/pp/node.rb +25 -26
  144. data/lib/nokogiri/xml/pp.rb +4 -2
  145. data/lib/nokogiri/xml/processing_instruction.rb +3 -1
  146. data/lib/nokogiri/xml/reader.rb +21 -28
  147. data/lib/nokogiri/xml/relax_ng.rb +8 -2
  148. data/lib/nokogiri/xml/sax/document.rb +45 -49
  149. data/lib/nokogiri/xml/sax/parser.rb +38 -34
  150. data/lib/nokogiri/xml/sax/parser_context.rb +8 -3
  151. data/lib/nokogiri/xml/sax/push_parser.rb +6 -5
  152. data/lib/nokogiri/xml/sax.rb +6 -4
  153. data/lib/nokogiri/xml/schema.rb +19 -9
  154. data/lib/nokogiri/xml/searchable.rb +112 -72
  155. data/lib/nokogiri/xml/syntax_error.rb +6 -4
  156. data/lib/nokogiri/xml/text.rb +2 -0
  157. data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
  158. data/lib/nokogiri/xml/xpath.rb +15 -4
  159. data/lib/nokogiri/xml/xpath_context.rb +3 -3
  160. data/lib/nokogiri/xml.rb +38 -37
  161. data/lib/nokogiri/xslt/stylesheet.rb +3 -1
  162. data/lib/nokogiri/xslt.rb +29 -20
  163. data/lib/nokogiri.rb +49 -65
  164. data/lib/xsd/xmlparser/nokogiri.rb +26 -24
  165. data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
  166. data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
  167. data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +25 -0
  168. data/patches/libxml2/0005-avoid-isnan-isinf.patch +81 -0
  169. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  170. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +3037 -0
  171. data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
  172. data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
  173. metadata +205 -138
  174. data/ext/nokogiri/html_document.c +0 -170
  175. data/ext/nokogiri/html_document.h +0 -10
  176. data/ext/nokogiri/html_element_description.c +0 -279
  177. data/ext/nokogiri/html_element_description.h +0 -10
  178. data/ext/nokogiri/html_entity_lookup.c +0 -32
  179. data/ext/nokogiri/html_entity_lookup.h +0 -8
  180. data/ext/nokogiri/html_sax_parser_context.c +0 -116
  181. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  182. data/ext/nokogiri/html_sax_push_parser.c +0 -87
  183. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  184. data/ext/nokogiri/xml_attr.h +0 -9
  185. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  186. data/ext/nokogiri/xml_cdata.h +0 -9
  187. data/ext/nokogiri/xml_comment.h +0 -9
  188. data/ext/nokogiri/xml_document.h +0 -23
  189. data/ext/nokogiri/xml_document_fragment.h +0 -10
  190. data/ext/nokogiri/xml_dtd.h +0 -10
  191. data/ext/nokogiri/xml_element_content.h +0 -10
  192. data/ext/nokogiri/xml_element_decl.h +0 -9
  193. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  194. data/ext/nokogiri/xml_entity_decl.h +0 -10
  195. data/ext/nokogiri/xml_entity_reference.h +0 -9
  196. data/ext/nokogiri/xml_io.c +0 -61
  197. data/ext/nokogiri/xml_io.h +0 -11
  198. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  199. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  200. data/ext/nokogiri/xml_namespace.h +0 -14
  201. data/ext/nokogiri/xml_node.h +0 -13
  202. data/ext/nokogiri/xml_node_set.h +0 -12
  203. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  204. data/ext/nokogiri/xml_reader.h +0 -10
  205. data/ext/nokogiri/xml_relax_ng.h +0 -9
  206. data/ext/nokogiri/xml_sax_parser.h +0 -39
  207. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  208. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  209. data/ext/nokogiri/xml_schema.h +0 -9
  210. data/ext/nokogiri/xml_syntax_error.h +0 -13
  211. data/ext/nokogiri/xml_text.h +0 -9
  212. data/ext/nokogiri/xml_xpath_context.h +0 -10
  213. data/ext/nokogiri/xslt_stylesheet.h +0 -14
  214. data/lib/nokogiri/html/document_fragment.rb +0 -49
  215. data/lib/nokogiri/html/element_description_defaults.rb +0 -671
  216. data/lib/nokogiri/html/sax/parser_context.rb +0 -16
  217. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  218. data/patches/libxslt/0001-Fix-security-framework-bypass.patch +0 -120
  219. data/ports/archives/libxml2-2.9.9.tar.gz +0 -0
  220. data/ports/archives/libxslt-1.1.33.tar.gz +0 -0
@@ -1,36 +1,71 @@
1
- #include <xml_node.h>
1
+ #include <nokogiri.h>
2
2
 
3
- static ID decorate, decorate_bang;
3
+ // :stopdoc:
4
+
5
+ VALUE cNokogiriXmlNode ;
6
+ static ID id_decorate, id_decorate_bang;
7
+
8
+ typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
4
9
 
5
10
  #ifdef DEBUG
6
- static void debug_node_dealloc(xmlNodePtr x)
11
+ static void
12
+ _xml_node_dealloc(xmlNodePtr x)
7
13
  {
8
14
  NOKOGIRI_DEBUG_START(x)
9
15
  NOKOGIRI_DEBUG_END(x)
10
16
  }
11
17
  #else
12
- # define debug_node_dealloc 0
18
+ # define _xml_node_dealloc 0
13
19
  #endif
14
20
 
15
- static void mark(xmlNodePtr node)
21
+ static void
22
+ _xml_node_mark(xmlNodePtr node)
16
23
  {
24
+ if (!DOC_RUBY_OBJECT_TEST(node->doc)) {
25
+ return;
26
+ }
27
+
17
28
  xmlDocPtr doc = node->doc;
18
- if(doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
19
- if(DOC_RUBY_OBJECT_TEST(doc)) {
29
+ if (doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
30
+ if (DOC_RUBY_OBJECT_TEST(doc)) {
20
31
  rb_gc_mark(DOC_RUBY_OBJECT(doc));
21
32
  }
22
- } else if(node->doc->_private) {
33
+ } else if (node->doc->_private) {
23
34
  rb_gc_mark((VALUE)doc->_private);
24
35
  }
25
36
  }
26
37
 
27
- /* :nodoc: */
28
- typedef xmlNodePtr (*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
38
+ #ifdef HAVE_RB_GC_LOCATION
39
+ static void
40
+ _xml_node_update_references(xmlNodePtr node)
41
+ {
42
+ if (node->_private) {
43
+ node->_private = (void *)rb_gc_location((VALUE)node->_private);
44
+ }
45
+ }
46
+ #endif
29
47
 
30
- /* :nodoc: */
31
- static void relink_namespace(xmlNodePtr reparented)
48
+ typedef void (*gc_callback_t)(void *);
49
+
50
+ static const rb_data_type_t nokogiri_node_type = {
51
+ "Nokogiri/XMLNode",
52
+ {
53
+ (gc_callback_t)_xml_node_mark, (gc_callback_t)_xml_node_dealloc, 0,
54
+ #ifdef HAVE_RB_GC_LOCATION
55
+ (gc_callback_t)_xml_node_update_references
56
+ #endif
57
+ },
58
+ 0, 0,
59
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
60
+ RUBY_TYPED_FREE_IMMEDIATELY,
61
+ #endif
62
+ };
63
+
64
+ static void
65
+ relink_namespace(xmlNodePtr reparented)
32
66
  {
33
67
  xmlNodePtr child;
68
+ xmlAttrPtr attr;
34
69
 
35
70
  if (reparented->type != XML_ATTRIBUTE_NODE &&
36
71
  reparented->type != XML_ELEMENT_NODE) { return; }
@@ -42,7 +77,7 @@ static void relink_namespace(xmlNodePtr reparented)
42
77
  name = xmlSplitQName2(reparented->name, &prefix);
43
78
 
44
79
  if (reparented->type == XML_ATTRIBUTE_NODE) {
45
- if (prefix == NULL || strcmp((char*)prefix, XMLNS_PREFIX) == 0) {
80
+ if (prefix == NULL || strcmp((char *)prefix, XMLNS_PREFIX) == 0) {
46
81
  xmlFree(name);
47
82
  xmlFree(prefix);
48
83
  return;
@@ -64,7 +99,9 @@ static void relink_namespace(xmlNodePtr reparented)
64
99
  if (reparented->type != XML_ELEMENT_NODE || !reparented->parent) { return; }
65
100
 
66
101
  /* Make sure that our reparented node has the correct namespaces */
67
- if (!reparented->ns && reparented->doc != (xmlDocPtr)reparented->parent) {
102
+ if (!reparented->ns &&
103
+ (reparented->doc != (xmlDocPtr)reparented->parent) &&
104
+ (rb_iv_get(DOC_RUBY_OBJECT(reparented->doc), "@namespace_inheritance") == Qtrue)) {
68
105
  xmlSetNs(reparented, reparented->parent->ns);
69
106
  }
70
107
 
@@ -87,7 +124,7 @@ static void relink_namespace(xmlNodePtr reparented)
87
124
  } else {
88
125
  reparented->nsDef = curr->next;
89
126
  }
90
- nokogiri_root_nsdef(curr, reparented->doc);
127
+ noko_xml_document_pin_namespace(curr, reparented->doc);
91
128
  } else {
92
129
  prev = curr;
93
130
  }
@@ -127,16 +164,19 @@ static void relink_namespace(xmlNodePtr reparented)
127
164
  }
128
165
 
129
166
  if (reparented->type == XML_ELEMENT_NODE) {
130
- child = (xmlNodePtr)((xmlElementPtr)reparented)->attributes;
131
- while(NULL != child) {
132
- relink_namespace(child);
133
- child = child->next;
167
+ attr = reparented->properties;
168
+ while (NULL != attr) {
169
+ relink_namespace((xmlNodePtr)attr);
170
+ attr = attr->next;
134
171
  }
135
172
  }
136
173
  }
137
174
 
138
- /* :nodoc: */
139
- static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
175
+
176
+ /* internal function meant to wrap xmlReplaceNode
177
+ and fix some issues we have with libxml2 merging nodes */
178
+ static xmlNodePtr
179
+ xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
140
180
  {
141
181
  xmlNodePtr retval ;
142
182
 
@@ -159,22 +199,34 @@ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
159
199
  return retval ;
160
200
  }
161
201
 
162
- /* :nodoc: */
163
- static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
202
+
203
+ static void
204
+ raise_if_ancestor_of_self(xmlNodePtr self)
205
+ {
206
+ for (xmlNodePtr ancestor = self->parent ; ancestor ; ancestor = ancestor->parent) {
207
+ if (self == ancestor) {
208
+ rb_raise(rb_eRuntimeError, "cycle detected: node '%s' is an ancestor of itself", self->name);
209
+ }
210
+ }
211
+ }
212
+
213
+
214
+ static VALUE
215
+ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
164
216
  {
165
217
  VALUE reparented_obj ;
166
- xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text, parent ;
218
+ xmlNodePtr reparentee, original_reparentee, pivot, reparented, next_text, new_next_text, parent ;
167
219
  int original_ns_prefix_is_default = 0 ;
168
220
 
169
- if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
221
+ if (!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
170
222
  rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
171
223
  }
172
- if(rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
224
+ if (rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
173
225
  rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
174
226
  }
175
227
 
176
- Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
177
- Data_Get_Struct(pivot_obj, xmlNode, pivot);
228
+ Noko_Node_Get_Struct(reparentee_obj, xmlNode, reparentee);
229
+ Noko_Node_Get_Struct(pivot_obj, xmlNode, pivot);
178
230
 
179
231
  /*
180
232
  * Check if nodes given are appropriate to have a parent-child
@@ -190,66 +242,66 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
190
242
 
191
243
  if (parent) {
192
244
  switch (parent->type) {
193
- case XML_DOCUMENT_NODE:
194
- case XML_HTML_DOCUMENT_NODE:
195
- switch (reparentee->type) {
196
- case XML_ELEMENT_NODE:
197
- case XML_PI_NODE:
198
- case XML_COMMENT_NODE:
199
- case XML_DOCUMENT_TYPE_NODE:
200
- /*
201
- * The DOM specification says no to adding text-like nodes
202
- * directly to a document, but we allow it for compatibility.
203
- */
204
- case XML_TEXT_NODE:
205
- case XML_CDATA_SECTION_NODE:
206
- case XML_ENTITY_REF_NODE:
207
- goto ok;
208
- default:
245
+ case XML_DOCUMENT_NODE:
246
+ case XML_HTML_DOCUMENT_NODE:
247
+ switch (reparentee->type) {
248
+ case XML_ELEMENT_NODE:
249
+ case XML_PI_NODE:
250
+ case XML_COMMENT_NODE:
251
+ case XML_DOCUMENT_TYPE_NODE:
252
+ /*
253
+ * The DOM specification says no to adding text-like nodes
254
+ * directly to a document, but we allow it for compatibility.
255
+ */
256
+ case XML_TEXT_NODE:
257
+ case XML_CDATA_SECTION_NODE:
258
+ case XML_ENTITY_REF_NODE:
259
+ goto ok;
260
+ default:
261
+ break;
262
+ }
209
263
  break;
210
- }
211
- break;
212
- case XML_DOCUMENT_FRAG_NODE:
213
- case XML_ENTITY_REF_NODE:
214
- case XML_ELEMENT_NODE:
215
- switch (reparentee->type) {
216
- case XML_ELEMENT_NODE:
217
- case XML_PI_NODE:
218
- case XML_COMMENT_NODE:
219
- case XML_TEXT_NODE:
220
- case XML_CDATA_SECTION_NODE:
264
+ case XML_DOCUMENT_FRAG_NODE:
221
265
  case XML_ENTITY_REF_NODE:
222
- goto ok;
223
- default:
266
+ case XML_ELEMENT_NODE:
267
+ switch (reparentee->type) {
268
+ case XML_ELEMENT_NODE:
269
+ case XML_PI_NODE:
270
+ case XML_COMMENT_NODE:
271
+ case XML_TEXT_NODE:
272
+ case XML_CDATA_SECTION_NODE:
273
+ case XML_ENTITY_REF_NODE:
274
+ goto ok;
275
+ default:
276
+ break;
277
+ }
278
+ break;
279
+ case XML_ATTRIBUTE_NODE:
280
+ switch (reparentee->type) {
281
+ case XML_TEXT_NODE:
282
+ case XML_ENTITY_REF_NODE:
283
+ goto ok;
284
+ default:
285
+ break;
286
+ }
224
287
  break;
225
- }
226
- break;
227
- case XML_ATTRIBUTE_NODE:
228
- switch (reparentee->type) {
229
288
  case XML_TEXT_NODE:
230
- case XML_ENTITY_REF_NODE:
231
- goto ok;
289
+ /*
290
+ * xmlAddChild() breaks the DOM specification in that it allows
291
+ * adding a text node to another, in which case text nodes are
292
+ * coalesced, but since our JRuby version does not support such
293
+ * operation, we should inhibit it.
294
+ */
295
+ break;
232
296
  default:
233
297
  break;
234
- }
235
- break;
236
- case XML_TEXT_NODE:
237
- /*
238
- * xmlAddChild() breaks the DOM specification in that it allows
239
- * adding a text node to another, in which case text nodes are
240
- * coalesced, but since our JRuby version does not support such
241
- * operation, we should inhibit it.
242
- */
243
- break;
244
- default:
245
- break;
246
298
  }
247
299
 
248
300
  rb_raise(rb_eArgError, "cannot reparent %s there", rb_obj_classname(reparentee_obj));
249
301
  }
250
302
 
251
303
  ok:
252
- xmlUnlinkNode(reparentee);
304
+ original_reparentee = reparentee;
253
305
 
254
306
  if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
255
307
  /*
@@ -290,7 +342,7 @@ ok:
290
342
  original_ns_prefix_is_default = 1;
291
343
  }
292
344
 
293
- nokogiri_root_node(reparentee);
345
+ noko_xml_document_pin_node(reparentee);
294
346
 
295
347
  if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
296
348
  rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
@@ -301,11 +353,13 @@ ok:
301
353
  * issue #391, where new node's prefix may become the string "default"
302
354
  * see libxml2 tree.c xmlNewReconciliedNs which implements this behavior.
303
355
  */
304
- xmlFree(reparentee->ns->prefix);
356
+ xmlFree(DISCARD_CONST_QUAL_XMLCHAR(reparentee->ns->prefix));
305
357
  reparentee->ns->prefix = NULL;
306
358
  }
307
359
  }
308
360
 
361
+ xmlUnlinkNode(original_reparentee);
362
+
309
363
  if (prf != xmlAddPrevSibling && prf != xmlAddNextSibling
310
364
  && reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
311
365
  /*
@@ -330,12 +384,12 @@ ok:
330
384
  new_next_text = xmlDocCopyNode(next_text, pivot->doc, 1) ;
331
385
 
332
386
  xmlUnlinkNode(next_text);
333
- nokogiri_root_node(next_text);
387
+ noko_xml_document_pin_node(next_text);
334
388
 
335
389
  xmlAddNextSibling(pivot, new_next_text);
336
390
  }
337
391
 
338
- if(!(reparented = (*prf)(pivot, reparentee))) {
392
+ if (!(reparented = (*prf)(pivot, reparentee))) {
339
393
  rb_raise(rb_eRuntimeError, "Could not reparent node");
340
394
  }
341
395
 
@@ -345,57 +399,432 @@ ok:
345
399
  * adjacent text nodes.
346
400
  */
347
401
  DATA_PTR(reparentee_obj) = reparented ;
402
+ reparented_obj = noko_xml_node_wrap(Qnil, reparented);
348
403
 
349
- relink_namespace(reparented);
404
+ rb_funcall(reparented_obj, id_decorate_bang, 0);
350
405
 
351
- reparented_obj = Nokogiri_wrap_xml_node(Qnil, reparented);
406
+ /* if we've created a cycle, raise an exception */
407
+ raise_if_ancestor_of_self(reparented);
352
408
 
353
- rb_funcall(reparented_obj, decorate_bang, 0);
409
+ relink_namespace(reparented);
354
410
 
355
411
  return reparented_obj ;
356
412
  }
357
413
 
414
+ // :startdoc:
358
415
 
359
416
  /*
360
- * call-seq:
361
- * document
417
+ * :call-seq:
418
+ * add_namespace_definition(prefix, href) → Nokogiri::XML::Namespace
419
+ * add_namespace(prefix, href) → Nokogiri::XML::Namespace
420
+ *
421
+ * :category: Manipulating Document Structure
422
+ *
423
+ * Adds a namespace definition to this node with +prefix+ using +href+ value, as if this node had
424
+ * included an attribute "xmlns:prefix=href".
425
+ *
426
+ * A default namespace definition for this node can be added by passing +nil+ for +prefix+.
427
+ *
428
+ * [Parameters]
429
+ * - +prefix+ (String, +nil+) An {XML Name}[https://www.w3.org/TR/xml-names/#ns-decl]
430
+ * - +href+ (String) The {URI reference}[https://www.w3.org/TR/xml-names/#sec-namespaces]
431
+ *
432
+ * [Returns] The new Nokogiri::XML::Namespace
433
+ *
434
+ * *Example:* adding a non-default namespace definition
435
+ *
436
+ * doc = Nokogiri::XML("<store><inventory></inventory></store>")
437
+ * inventory = doc.at_css("inventory")
438
+ * inventory.add_namespace_definition("automobile", "http://alices-autos.com/")
439
+ * inventory.add_namespace_definition("bicycle", "http://bobs-bikes.com/")
440
+ * inventory.add_child("<automobile:tire>Michelin model XGV, size 75R</automobile:tire>")
441
+ * doc.to_xml
442
+ * # => "<?xml version=\"1.0\"?>\n" +
443
+ * # "<store>\n" +
444
+ * # " <inventory xmlns:automobile=\"http://alices-autos.com/\" xmlns:bicycle=\"http://bobs-bikes.com/\">\n" +
445
+ * # " <automobile:tire>Michelin model XGV, size 75R</automobile:tire>\n" +
446
+ * # " </inventory>\n" +
447
+ * # "</store>\n"
448
+ *
449
+ * *Example:* adding a default namespace definition
450
+ *
451
+ * doc = Nokogiri::XML("<store><inventory><tire>Michelin model XGV, size 75R</tire></inventory></store>")
452
+ * doc.at_css("tire").add_namespace_definition(nil, "http://bobs-bikes.com/")
453
+ * doc.to_xml
454
+ * # => "<?xml version=\"1.0\"?>\n" +
455
+ * # "<store>\n" +
456
+ * # " <inventory>\n" +
457
+ * # " <tire xmlns=\"http://bobs-bikes.com/\">Michelin model XGV, size 75R</tire>\n" +
458
+ * # " </inventory>\n" +
459
+ * # "</store>\n"
460
+ *
461
+ */
462
+ static VALUE
463
+ rb_xml_node_add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
464
+ {
465
+ xmlNodePtr c_node, element;
466
+ xmlNsPtr c_namespace;
467
+ const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
468
+
469
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
470
+ element = c_node ;
471
+
472
+ c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
473
+
474
+ if (!c_namespace) {
475
+ if (c_node->type != XML_ELEMENT_NODE) {
476
+ element = c_node->parent;
477
+ }
478
+ c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
479
+ }
480
+
481
+ if (!c_namespace) {
482
+ return Qnil ;
483
+ }
484
+
485
+ if (NIL_P(rb_prefix) || c_node != element) {
486
+ xmlSetNs(c_node, c_namespace);
487
+ }
488
+
489
+ return noko_xml_namespace_wrap(c_namespace, c_node->doc);
490
+ }
491
+
492
+
493
+ /*
494
+ * :call-seq: attribute(name) → Nokogiri::XML::Attr
495
+ *
496
+ * :category: Working With Node Attributes
497
+ *
498
+ * [Returns] Attribute (Nokogiri::XML::Attr) belonging to this node with name +name+.
499
+ *
500
+ * ⚠ Note that attribute namespaces are ignored and only the simple (non-namespace-prefixed) name is
501
+ * used to find a matching attribute. In case of a simple name collision, only one of the matching
502
+ * attributes will be returned. In this case, you will need to use #attribute_with_ns.
503
+ *
504
+ * *Example:*
505
+ *
506
+ * doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
507
+ * child = doc.at_css("child")
508
+ * child.attribute("size") # => #<Nokogiri::XML::Attr:0x550 name="size" value="large">
509
+ * child.attribute("class") # => #<Nokogiri::XML::Attr:0x564 name="class" value="big wide tall">
510
+ *
511
+ * *Example* showing that namespaced attributes will not be returned:
512
+ *
513
+ * ⚠ Note that only one of the two matching attributes is returned.
514
+ *
515
+ * doc = Nokogiri::XML(<<~EOF)
516
+ * <root xmlns:width='http://example.com/widths'
517
+ * xmlns:height='http://example.com/heights'>
518
+ * <child width:size='broad' height:size='tall'/>
519
+ * </root>
520
+ * EOF
521
+ * doc.at_css("child").attribute("size")
522
+ * # => #(Attr:0x550 {
523
+ * # name = "size",
524
+ * # namespace = #(Namespace:0x564 {
525
+ * # prefix = "width",
526
+ * # href = "http://example.com/widths"
527
+ * # }),
528
+ * # value = "broad"
529
+ * # })
530
+ */
531
+ static VALUE
532
+ rb_xml_node_attribute(VALUE self, VALUE name)
533
+ {
534
+ xmlNodePtr node;
535
+ xmlAttrPtr prop;
536
+ Noko_Node_Get_Struct(self, xmlNode, node);
537
+ prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
538
+
539
+ if (! prop) { return Qnil; }
540
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
541
+ }
542
+
543
+
544
+ /*
545
+ * :call-seq: attribute_nodes() → Array<Nokogiri::XML::Attr>
546
+ *
547
+ * :category: Working With Node Attributes
548
+ *
549
+ * [Returns] Attributes (an Array of Nokogiri::XML::Attr) belonging to this node.
550
+ *
551
+ * Note that this is the preferred alternative to #attributes when the simple
552
+ * (non-namespace-prefixed) attribute names may collide.
553
+ *
554
+ * *Example:*
555
+ *
556
+ * Contrast this with the colliding-name example from #attributes.
557
+ *
558
+ * doc = Nokogiri::XML(<<~EOF)
559
+ * <root xmlns:width='http://example.com/widths'
560
+ * xmlns:height='http://example.com/heights'>
561
+ * <child width:size='broad' height:size='tall'/>
562
+ * </root>
563
+ * EOF
564
+ * doc.at_css("child").attribute_nodes
565
+ * # => [#(Attr:0x550 {
566
+ * # name = "size",
567
+ * # namespace = #(Namespace:0x564 {
568
+ * # prefix = "width",
569
+ * # href = "http://example.com/widths"
570
+ * # }),
571
+ * # value = "broad"
572
+ * # }),
573
+ * # #(Attr:0x578 {
574
+ * # name = "size",
575
+ * # namespace = #(Namespace:0x58c {
576
+ * # prefix = "height",
577
+ * # href = "http://example.com/heights"
578
+ * # }),
579
+ * # value = "tall"
580
+ * # })]
581
+ */
582
+ static VALUE
583
+ rb_xml_node_attribute_nodes(VALUE rb_node)
584
+ {
585
+ xmlNodePtr c_node;
586
+
587
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
588
+
589
+ return noko_xml_node_attrs(c_node);
590
+ }
591
+
592
+
593
+ /*
594
+ * :call-seq: attribute_with_ns(name, namespace) → Nokogiri::XML::Attr
595
+ *
596
+ * :category: Working With Node Attributes
597
+ *
598
+ * [Returns]
599
+ * Attribute (Nokogiri::XML::Attr) belonging to this node with matching +name+ and +namespace+.
600
+ *
601
+ * [Parameters]
602
+ * - +name+ (String): the simple (non-namespace-prefixed) name of the attribute
603
+ * - +namespace+ (String): the URI of the attribute's namespace
604
+ *
605
+ * See related: #attribute
606
+ *
607
+ * *Example:*
608
+ *
609
+ * doc = Nokogiri::XML(<<~EOF)
610
+ * <root xmlns:width='http://example.com/widths'
611
+ * xmlns:height='http://example.com/heights'>
612
+ * <child width:size='broad' height:size='tall'/>
613
+ * </root>
614
+ * EOF
615
+ * doc.at_css("child").attribute_with_ns("size", "http://example.com/widths")
616
+ * # => #(Attr:0x550 {
617
+ * # name = "size",
618
+ * # namespace = #(Namespace:0x564 {
619
+ * # prefix = "width",
620
+ * # href = "http://example.com/widths"
621
+ * # }),
622
+ * # value = "broad"
623
+ * # })
624
+ * doc.at_css("child").attribute_with_ns("size", "http://example.com/heights")
625
+ * # => #(Attr:0x578 {
626
+ * # name = "size",
627
+ * # namespace = #(Namespace:0x58c {
628
+ * # prefix = "height",
629
+ * # href = "http://example.com/heights"
630
+ * # }),
631
+ * # value = "tall"
632
+ * # })
633
+ */
634
+ static VALUE
635
+ rb_xml_node_attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
636
+ {
637
+ xmlNodePtr node;
638
+ xmlAttrPtr prop;
639
+ Noko_Node_Get_Struct(self, xmlNode, node);
640
+ prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
641
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
642
+
643
+ if (! prop) { return Qnil; }
644
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
645
+ }
646
+
647
+
648
+
649
+ /*
650
+ * call-seq: blank? → Boolean
651
+ *
652
+ * [Returns] +true+ if the node is an empty or whitespace-only text or cdata node, else +false+.
653
+ *
654
+ * *Example:*
655
+ *
656
+ * Nokogiri("<root><child/></root>").root.child.blank? # => false
657
+ * Nokogiri("<root>\t \n</root>").root.child.blank? # => true
658
+ * Nokogiri("<root><![CDATA[\t \n]]></root>").root.child.blank? # => true
659
+ * Nokogiri("<root>not-blank</root>").root.child
660
+ * .tap { |n| n.content = "" }.blank # => true
661
+ */
662
+ static VALUE
663
+ rb_xml_node_blank_eh(VALUE self)
664
+ {
665
+ xmlNodePtr node;
666
+ Noko_Node_Get_Struct(self, xmlNode, node);
667
+ return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
668
+ }
669
+
670
+
671
+ /*
672
+ * :call-seq: child() → Nokogiri::XML::Node
673
+ *
674
+ * :category: Traversing Document Structure
675
+ *
676
+ * [Returns] First of this node's children, or +nil+ if there are no children
677
+ *
678
+ * This is a convenience method and is equivalent to:
679
+ *
680
+ * node.children.first
681
+ *
682
+ * See related: #children
683
+ */
684
+ static VALUE
685
+ rb_xml_node_child(VALUE self)
686
+ {
687
+ xmlNodePtr node, child;
688
+ Noko_Node_Get_Struct(self, xmlNode, node);
689
+
690
+ child = node->children;
691
+ if (!child) { return Qnil; }
692
+
693
+ return noko_xml_node_wrap(Qnil, child);
694
+ }
695
+
696
+
697
+ /*
698
+ * :call-seq: children() → Nokogiri::XML::NodeSet
699
+ *
700
+ * :category: Traversing Document Structure
701
+ *
702
+ * [Returns] Nokogiri::XML::NodeSet containing this node's children.
703
+ */
704
+ static VALUE
705
+ rb_xml_node_children(VALUE self)
706
+ {
707
+ xmlNodePtr node;
708
+ xmlNodePtr child;
709
+ xmlNodeSetPtr set;
710
+ VALUE document;
711
+ VALUE node_set;
712
+
713
+ Noko_Node_Get_Struct(self, xmlNode, node);
714
+
715
+ child = node->children;
716
+ set = xmlXPathNodeSetCreate(child);
717
+
718
+ document = DOC_RUBY_OBJECT(node->doc);
719
+
720
+ if (!child) { return noko_xml_node_set_wrap(set, document); }
721
+
722
+ child = child->next;
723
+ while (NULL != child) {
724
+ xmlXPathNodeSetAddUnique(set, child);
725
+ child = child->next;
726
+ }
727
+
728
+ node_set = noko_xml_node_set_wrap(set, document);
729
+
730
+ return node_set;
731
+ }
732
+
733
+
734
+ /*
735
+ * :call-seq:
736
+ * content() → String
737
+ * inner_text() → String
738
+ * text() → String
739
+ * to_str() → String
740
+ *
741
+ * [Returns]
742
+ * Contents of all the text nodes in this node's subtree, concatenated together into a single
743
+ * String.
744
+ *
745
+ * ⚠ Note that entities will _always_ be expanded in the returned String.
362
746
  *
363
- * Get the document for this Node
747
+ * See related: #inner_html
748
+ *
749
+ * *Example* of how entities are handled:
750
+ *
751
+ * Note that <tt>&lt;</tt> becomes <tt><</tt> in the returned String.
752
+ *
753
+ * doc = Nokogiri::XML.fragment("<child>a &lt; b</child>")
754
+ * doc.at_css("child").content
755
+ * # => "a < b"
756
+ *
757
+ * *Example* of how a subtree is handled:
758
+ *
759
+ * Note that the <tt><span></tt> tags are omitted and only the text node contents are returned,
760
+ * concatenated into a single string.
761
+ *
762
+ * doc = Nokogiri::XML.fragment("<child><span>first</span> <span>second</span></child>")
763
+ * doc.at_css("child").content
764
+ * # => "first second"
364
765
  */
365
- static VALUE document(VALUE self)
766
+ static VALUE
767
+ rb_xml_node_content(VALUE self)
366
768
  {
367
769
  xmlNodePtr node;
368
- Data_Get_Struct(self, xmlNode, node);
770
+ xmlChar *content;
771
+
772
+ Noko_Node_Get_Struct(self, xmlNode, node);
773
+
774
+ content = xmlNodeGetContent(node);
775
+ if (content) {
776
+ VALUE rval = NOKOGIRI_STR_NEW2(content);
777
+ xmlFree(content);
778
+ return rval;
779
+ }
780
+ return Qnil;
781
+ }
782
+
783
+
784
+ /*
785
+ * :call-seq: document() → Nokogiri::XML::Document
786
+ *
787
+ * :category: Traversing Document Structure
788
+ *
789
+ * [Returns] Parent Nokogiri::XML::Document for this node
790
+ */
791
+ static VALUE
792
+ rb_xml_node_document(VALUE self)
793
+ {
794
+ xmlNodePtr node;
795
+ Noko_Node_Get_Struct(self, xmlNode, node);
369
796
  return DOC_RUBY_OBJECT(node->doc);
370
797
  }
371
798
 
372
799
  /*
373
- * call-seq:
374
- * pointer_id
800
+ * :call-seq: pointer_id() → Integer
375
801
  *
376
- * Get the internal pointer number
802
+ * [Returns]
803
+ * A unique id for this node based on the internal memory structures. This method is used by #==
804
+ * to determine node identity.
377
805
  */
378
- static VALUE pointer_id(VALUE self)
806
+ static VALUE
807
+ rb_xml_node_pointer_id(VALUE self)
379
808
  {
380
809
  xmlNodePtr node;
381
- Data_Get_Struct(self, xmlNode, node);
810
+ Noko_Node_Get_Struct(self, xmlNode, node);
382
811
 
383
812
  return INT2NUM((long)(node));
384
813
  }
385
814
 
386
815
  /*
387
- * call-seq:
388
- * encode_special_chars(string)
816
+ * :call-seq: encode_special_chars(string) → String
389
817
  *
390
818
  * Encode any special characters in +string+
391
819
  */
392
- static VALUE encode_special_chars(VALUE self, VALUE string)
820
+ static VALUE
821
+ encode_special_chars(VALUE self, VALUE string)
393
822
  {
394
823
  xmlNodePtr node;
395
824
  xmlChar *encoded;
396
825
  VALUE encoded_str;
397
826
 
398
- Data_Get_Struct(self, xmlNode, node);
827
+ Noko_Node_Get_Struct(self, xmlNode, node);
399
828
  encoded = xmlEncodeSpecialChars(
400
829
  node->doc,
401
830
  (const xmlChar *)StringValueCStr(string)
@@ -408,8 +837,8 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
408
837
  }
409
838
 
410
839
  /*
411
- * call-seq:
412
- * create_internal_subset(name, external_id, system_id)
840
+ * :call-seq:
841
+ * create_internal_subset(name, external_id, system_id)
413
842
  *
414
843
  * Create the internal subset of a document.
415
844
  *
@@ -419,17 +848,18 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
419
848
  * doc.create_internal_subset("chapter", nil, "chapter.dtd")
420
849
  * # => <!DOCTYPE chapter SYSTEM "chapter.dtd">
421
850
  */
422
- static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
851
+ static VALUE
852
+ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
423
853
  {
424
854
  xmlNodePtr node;
425
855
  xmlDocPtr doc;
426
856
  xmlDtdPtr dtd;
427
857
 
428
- Data_Get_Struct(self, xmlNode, node);
858
+ Noko_Node_Get_Struct(self, xmlNode, node);
429
859
 
430
860
  doc = node->doc;
431
861
 
432
- if(xmlGetIntSubset(doc)) {
862
+ if (xmlGetIntSubset(doc)) {
433
863
  rb_raise(rb_eRuntimeError, "Document already has an internal subset");
434
864
  }
435
865
 
@@ -440,28 +870,29 @@ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, V
440
870
  NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
441
871
  );
442
872
 
443
- if(!dtd) { return Qnil; }
873
+ if (!dtd) { return Qnil; }
444
874
 
445
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
875
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
446
876
  }
447
877
 
448
878
  /*
449
- * call-seq:
450
- * create_external_subset(name, external_id, system_id)
879
+ * :call-seq:
880
+ * create_external_subset(name, external_id, system_id)
451
881
  *
452
882
  * Create an external subset
453
883
  */
454
- static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
884
+ static VALUE
885
+ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
455
886
  {
456
887
  xmlNodePtr node;
457
888
  xmlDocPtr doc;
458
889
  xmlDtdPtr dtd;
459
890
 
460
- Data_Get_Struct(self, xmlNode, node);
891
+ Noko_Node_Get_Struct(self, xmlNode, node);
461
892
 
462
893
  doc = node->doc;
463
894
 
464
- if(doc->extSubset) {
895
+ if (doc->extSubset) {
465
896
  rb_raise(rb_eRuntimeError, "Document already has an external subset");
466
897
  }
467
898
 
@@ -472,72 +903,78 @@ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, V
472
903
  NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
473
904
  );
474
905
 
475
- if(!dtd) { return Qnil; }
906
+ if (!dtd) { return Qnil; }
476
907
 
477
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
908
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
478
909
  }
479
910
 
480
911
  /*
481
- * call-seq:
482
- * external_subset
912
+ * :call-seq:
913
+ * external_subset()
483
914
  *
484
915
  * Get the external subset
485
916
  */
486
- static VALUE external_subset(VALUE self)
917
+ static VALUE
918
+ external_subset(VALUE self)
487
919
  {
488
920
  xmlNodePtr node;
489
921
  xmlDocPtr doc;
490
922
  xmlDtdPtr dtd;
491
923
 
492
- Data_Get_Struct(self, xmlNode, node);
924
+ Noko_Node_Get_Struct(self, xmlNode, node);
493
925
 
494
- if(!node->doc) { return Qnil; }
926
+ if (!node->doc) { return Qnil; }
495
927
 
496
928
  doc = node->doc;
497
929
  dtd = doc->extSubset;
498
930
 
499
- if(!dtd) { return Qnil; }
931
+ if (!dtd) { return Qnil; }
500
932
 
501
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
933
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
502
934
  }
503
935
 
504
936
  /*
505
- * call-seq:
506
- * internal_subset
937
+ * :call-seq:
938
+ * internal_subset()
507
939
  *
508
940
  * Get the internal subset
509
941
  */
510
- static VALUE internal_subset(VALUE self)
942
+ static VALUE
943
+ internal_subset(VALUE self)
511
944
  {
512
945
  xmlNodePtr node;
513
946
  xmlDocPtr doc;
514
947
  xmlDtdPtr dtd;
515
948
 
516
- Data_Get_Struct(self, xmlNode, node);
949
+ Noko_Node_Get_Struct(self, xmlNode, node);
517
950
 
518
- if(!node->doc) { return Qnil; }
951
+ if (!node->doc) { return Qnil; }
519
952
 
520
953
  doc = node->doc;
521
954
  dtd = xmlGetIntSubset(doc);
522
955
 
523
- if(!dtd) { return Qnil; }
956
+ if (!dtd) { return Qnil; }
524
957
 
525
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
958
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
526
959
  }
527
960
 
528
961
  /*
529
- * call-seq:
530
- * dup
531
- * dup(depth)
532
- * dup(depth, new_parent_doc)
962
+ * :call-seq:
963
+ * dup → Nokogiri::XML::Node
964
+ * dup(depth) → Nokogiri::XML::Node
965
+ * dup(depth, new_parent_doc) → Nokogiri::XML::Node
533
966
  *
534
967
  * Copy this node.
535
- * An optional depth may be passed in. 0 is a shallow copy, 1 (the default) is a deep copy.
536
- * An optional new_parent_doc may also be passed in, which will be the new
537
- * node's parent document. Defaults to the current node's document.
538
- * current document.
968
+ *
969
+ * [Parameters]
970
+ * - +depth+ 0 is a shallow copy, 1 (the default) is a deep copy.
971
+ * - +new_parent_doc+
972
+ * The new node's parent Document. Defaults to the this node's document.
973
+ *
974
+ * [Returns] The new Nokgiri::XML::Node
539
975
  */
540
- static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
976
+ static VALUE
977
+ duplicate_node(int argc, VALUE *argv, VALUE self)
541
978
  {
542
979
  VALUE r_level, r_new_parent_doc;
543
980
  int level;
@@ -545,7 +982,7 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
545
982
  xmlDocPtr new_parent_doc;
546
983
  xmlNodePtr node, dup;
547
984
 
548
- Data_Get_Struct(self, xmlNode, node);
985
+ Noko_Node_Get_Struct(self, xmlNode, node);
549
986
 
550
987
  n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
551
988
 
@@ -561,40 +998,29 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
561
998
  }
562
999
 
563
1000
  dup = xmlDocCopyNode(node, new_parent_doc, level);
564
- if(dup == NULL) { return Qnil; }
1001
+ if (dup == NULL) { return Qnil; }
565
1002
 
566
- nokogiri_root_node(dup);
1003
+ noko_xml_document_pin_node(dup);
567
1004
 
568
- return Nokogiri_wrap_xml_node(rb_obj_class(self), dup);
1005
+ return noko_xml_node_wrap(rb_obj_class(self), dup);
569
1006
  }
570
1007
 
571
1008
  /*
572
- * call-seq:
573
- * unlink
1009
+ * :call-seq:
1010
+ * unlink() → self
574
1011
  *
575
1012
  * Unlink this node from its current context.
576
1013
  */
577
- static VALUE unlink_node(VALUE self)
1014
+ static VALUE
1015
+ unlink_node(VALUE self)
578
1016
  {
579
1017
  xmlNodePtr node;
580
- Data_Get_Struct(self, xmlNode, node);
1018
+ Noko_Node_Get_Struct(self, xmlNode, node);
581
1019
  xmlUnlinkNode(node);
582
- nokogiri_root_node(node);
1020
+ noko_xml_document_pin_node(node);
583
1021
  return self;
584
1022
  }
585
1023
 
586
- /*
587
- * call-seq:
588
- * blank?
589
- *
590
- * Is this node blank?
591
- */
592
- static VALUE blank_eh(VALUE self)
593
- {
594
- xmlNodePtr node;
595
- Data_Get_Struct(self, xmlNode, node);
596
- return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
597
- }
598
1024
 
599
1025
  /*
600
1026
  * call-seq:
@@ -602,15 +1028,16 @@ static VALUE blank_eh(VALUE self)
602
1028
  *
603
1029
  * Returns the next sibling node
604
1030
  */
605
- static VALUE next_sibling(VALUE self)
1031
+ static VALUE
1032
+ next_sibling(VALUE self)
606
1033
  {
607
1034
  xmlNodePtr node, sibling;
608
- Data_Get_Struct(self, xmlNode, node);
1035
+ Noko_Node_Get_Struct(self, xmlNode, node);
609
1036
 
610
1037
  sibling = node->next;
611
- if(!sibling) { return Qnil; }
1038
+ if (!sibling) { return Qnil; }
612
1039
 
613
- return Nokogiri_wrap_xml_node(Qnil, sibling) ;
1040
+ return noko_xml_node_wrap(Qnil, sibling) ;
614
1041
  }
615
1042
 
616
1043
  /*
@@ -619,15 +1046,16 @@ static VALUE next_sibling(VALUE self)
619
1046
  *
620
1047
  * Returns the previous sibling node
621
1048
  */
622
- static VALUE previous_sibling(VALUE self)
1049
+ static VALUE
1050
+ previous_sibling(VALUE self)
623
1051
  {
624
1052
  xmlNodePtr node, sibling;
625
- Data_Get_Struct(self, xmlNode, node);
1053
+ Noko_Node_Get_Struct(self, xmlNode, node);
626
1054
 
627
1055
  sibling = node->prev;
628
- if(!sibling) { return Qnil; }
1056
+ if (!sibling) { return Qnil; }
629
1057
 
630
- return Nokogiri_wrap_xml_node(Qnil, sibling);
1058
+ return noko_xml_node_wrap(Qnil, sibling);
631
1059
  }
632
1060
 
633
1061
  /*
@@ -636,15 +1064,16 @@ static VALUE previous_sibling(VALUE self)
636
1064
  *
637
1065
  * Returns the next Nokogiri::XML::Element type sibling node.
638
1066
  */
639
- static VALUE next_element(VALUE self)
1067
+ static VALUE
1068
+ next_element(VALUE self)
640
1069
  {
641
1070
  xmlNodePtr node, sibling;
642
- Data_Get_Struct(self, xmlNode, node);
1071
+ Noko_Node_Get_Struct(self, xmlNode, node);
643
1072
 
644
1073
  sibling = xmlNextElementSibling(node);
645
- if(!sibling) { return Qnil; }
1074
+ if (!sibling) { return Qnil; }
646
1075
 
647
- return Nokogiri_wrap_xml_node(Qnil, sibling);
1076
+ return noko_xml_node_wrap(Qnil, sibling);
648
1077
  }
649
1078
 
650
1079
  /*
@@ -653,82 +1082,60 @@ static VALUE next_element(VALUE self)
653
1082
  *
654
1083
  * Returns the previous Nokogiri::XML::Element type sibling node.
655
1084
  */
656
- static VALUE previous_element(VALUE self)
1085
+ static VALUE
1086
+ previous_element(VALUE self)
657
1087
  {
658
1088
  xmlNodePtr node, sibling;
659
- Data_Get_Struct(self, xmlNode, node);
1089
+ Noko_Node_Get_Struct(self, xmlNode, node);
660
1090
 
661
1091
  /*
662
1092
  * note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
663
1093
  */
664
1094
  sibling = node->prev;
665
- if(!sibling) { return Qnil; }
1095
+ if (!sibling) { return Qnil; }
666
1096
 
667
- while(sibling && sibling->type != XML_ELEMENT_NODE) {
1097
+ while (sibling && sibling->type != XML_ELEMENT_NODE) {
668
1098
  sibling = sibling->prev;
669
1099
  }
670
1100
 
671
- return sibling ? Nokogiri_wrap_xml_node(Qnil, sibling) : Qnil ;
1101
+ return sibling ? noko_xml_node_wrap(Qnil, sibling) : Qnil ;
672
1102
  }
673
1103
 
674
1104
  /* :nodoc: */
675
- static VALUE replace(VALUE self, VALUE new_node)
1105
+ static VALUE
1106
+ replace(VALUE self, VALUE new_node)
676
1107
  {
677
1108
  VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
678
1109
 
679
1110
  xmlNodePtr pivot;
680
- Data_Get_Struct(self, xmlNode, pivot);
681
- nokogiri_root_node(pivot);
1111
+ Noko_Node_Get_Struct(self, xmlNode, pivot);
1112
+ noko_xml_document_pin_node(pivot);
682
1113
 
683
1114
  return reparent;
684
1115
  }
685
1116
 
686
1117
  /*
687
- * call-seq:
688
- * children
1118
+ * :call-seq:
1119
+ * element_children() → NodeSet
1120
+ * elements() → NodeSet
689
1121
  *
690
- * Get the list of children for this node as a NodeSet
691
- */
692
- static VALUE children(VALUE self)
693
- {
694
- xmlNodePtr node;
695
- xmlNodePtr child;
696
- xmlNodeSetPtr set;
697
- VALUE document;
698
- VALUE node_set;
699
-
700
- Data_Get_Struct(self, xmlNode, node);
701
-
702
- child = node->children;
703
- set = xmlXPathNodeSetCreate(child);
704
-
705
- document = DOC_RUBY_OBJECT(node->doc);
706
-
707
- if(!child) { return Nokogiri_wrap_xml_node_set(set, document); }
708
-
709
- child = child->next;
710
- while(NULL != child) {
711
- xmlXPathNodeSetAddUnique(set, child);
712
- child = child->next;
713
- }
714
-
715
- node_set = Nokogiri_wrap_xml_node_set(set, document);
716
-
717
- return node_set;
718
- }
719
-
720
- /*
721
- * call-seq:
722
- * element_children
1122
+ * [Returns]
1123
+ * The node's child elements as a NodeSet. Only children that are elements will be returned, which
1124
+ * notably excludes Text nodes.
723
1125
  *
724
- * Get the list of children for this node as a NodeSet. All nodes will be
725
- * element nodes.
1126
+ * *Example:*
726
1127
  *
727
- * Example:
1128
+ * Note that #children returns the Text node "hello" while #element_children does not.
728
1129
  *
729
- * @doc.root.element_children.all? { |x| x.element? } # => true
1130
+ * div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
1131
+ * div.element_children
1132
+ * # => [#<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
1133
+ * div.children
1134
+ * # => [#<Nokogiri::XML::Text:0x64 "hello">,
1135
+ * # #<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
730
1136
  */
731
- static VALUE element_children(VALUE self)
1137
+ static VALUE
1138
+ rb_xml_node_element_children(VALUE self)
732
1139
  {
733
1140
  xmlNodePtr node;
734
1141
  xmlNodePtr child;
@@ -736,83 +1143,78 @@ static VALUE element_children(VALUE self)
736
1143
  VALUE document;
737
1144
  VALUE node_set;
738
1145
 
739
- Data_Get_Struct(self, xmlNode, node);
1146
+ Noko_Node_Get_Struct(self, xmlNode, node);
740
1147
 
741
1148
  child = xmlFirstElementChild(node);
742
1149
  set = xmlXPathNodeSetCreate(child);
743
1150
 
744
1151
  document = DOC_RUBY_OBJECT(node->doc);
745
1152
 
746
- if(!child) { return Nokogiri_wrap_xml_node_set(set, document); }
1153
+ if (!child) { return noko_xml_node_set_wrap(set, document); }
747
1154
 
748
1155
  child = xmlNextElementSibling(child);
749
- while(NULL != child) {
1156
+ while (NULL != child) {
750
1157
  xmlXPathNodeSetAddUnique(set, child);
751
1158
  child = xmlNextElementSibling(child);
752
1159
  }
753
1160
 
754
- node_set = Nokogiri_wrap_xml_node_set(set, document);
1161
+ node_set = noko_xml_node_set_wrap(set, document);
755
1162
 
756
1163
  return node_set;
757
1164
  }
758
1165
 
759
1166
  /*
760
- * call-seq:
761
- * child
1167
+ * :call-seq:
1168
+ * first_element_child() → Node
762
1169
  *
763
- * Returns the child node
764
- */
765
- static VALUE child(VALUE self)
766
- {
767
- xmlNodePtr node, child;
768
- Data_Get_Struct(self, xmlNode, node);
769
-
770
- child = node->children;
771
- if(!child) { return Qnil; }
772
-
773
- return Nokogiri_wrap_xml_node(Qnil, child);
774
- }
775
-
776
- /*
777
- * call-seq:
778
- * first_element_child
1170
+ * [Returns] The first child Node that is an element.
779
1171
  *
780
- * Returns the first child node of this node that is an element.
1172
+ * *Example:*
781
1173
  *
782
- * Example:
1174
+ * Note that the "hello" child, which is a Text node, is skipped and the <tt><span></tt> element is
1175
+ * returned.
783
1176
  *
784
- * @doc.root.first_element_child.element? # => true
1177
+ * div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
1178
+ * div.first_element_child
1179
+ * # => #(Element:0x3c { name = "span", children = [ #(Text "world")] })
785
1180
  */
786
- static VALUE first_element_child(VALUE self)
1181
+ static VALUE
1182
+ rb_xml_node_first_element_child(VALUE self)
787
1183
  {
788
1184
  xmlNodePtr node, child;
789
- Data_Get_Struct(self, xmlNode, node);
1185
+ Noko_Node_Get_Struct(self, xmlNode, node);
790
1186
 
791
1187
  child = xmlFirstElementChild(node);
792
- if(!child) { return Qnil; }
1188
+ if (!child) { return Qnil; }
793
1189
 
794
- return Nokogiri_wrap_xml_node(Qnil, child);
1190
+ return noko_xml_node_wrap(Qnil, child);
795
1191
  }
796
1192
 
797
1193
  /*
798
- * call-seq:
799
- * last_element_child
1194
+ * :call-seq:
1195
+ * last_element_child() → Node
1196
+ *
1197
+ * [Returns] The last child Node that is an element.
800
1198
  *
801
- * Returns the last child node of this node that is an element.
1199
+ * *Example:*
802
1200
  *
803
- * Example:
1201
+ * Note that the "hello" child, which is a Text node, is skipped and the <tt><span>yes</span></tt>
1202
+ * element is returned.
804
1203
  *
805
- * @doc.root.last_element_child.element? # => true
1204
+ * div = Nokogiri::HTML5("<div><span>no</span><span>yes</span>skip</div>").at_css("div")
1205
+ * div.last_element_child
1206
+ * # => #(Element:0x3c { name = "span", children = [ #(Text "yes")] })
806
1207
  */
807
- static VALUE last_element_child(VALUE self)
1208
+ static VALUE
1209
+ rb_xml_node_last_element_child(VALUE self)
808
1210
  {
809
1211
  xmlNodePtr node, child;
810
- Data_Get_Struct(self, xmlNode, node);
1212
+ Noko_Node_Get_Struct(self, xmlNode, node);
811
1213
 
812
1214
  child = xmlLastElementChild(node);
813
- if(!child) { return Qnil; }
1215
+ if (!child) { return Qnil; }
814
1216
 
815
- return Nokogiri_wrap_xml_node(Qnil, child);
1217
+ return noko_xml_node_wrap(Qnil, child);
816
1218
  }
817
1219
 
818
1220
  /*
@@ -821,11 +1223,12 @@ static VALUE last_element_child(VALUE self)
821
1223
  *
822
1224
  * Returns true if +attribute+ is set
823
1225
  */
824
- static VALUE key_eh(VALUE self, VALUE attribute)
1226
+ static VALUE
1227
+ key_eh(VALUE self, VALUE attribute)
825
1228
  {
826
1229
  xmlNodePtr node;
827
- Data_Get_Struct(self, xmlNode, node);
828
- if(xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
1230
+ Noko_Node_Get_Struct(self, xmlNode, node);
1231
+ if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
829
1232
  return Qtrue;
830
1233
  }
831
1234
  return Qfalse;
@@ -837,12 +1240,13 @@ static VALUE key_eh(VALUE self, VALUE attribute)
837
1240
  *
838
1241
  * Returns true if +attribute+ is set with +namespace+
839
1242
  */
840
- static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
1243
+ static VALUE
1244
+ namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
841
1245
  {
842
1246
  xmlNodePtr node;
843
- Data_Get_Struct(self, xmlNode, node);
844
- if(xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
845
- NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
1247
+ Noko_Node_Get_Struct(self, xmlNode, node);
1248
+ if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
1249
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
846
1250
  return Qtrue;
847
1251
  }
848
1252
  return Qfalse;
@@ -854,11 +1258,12 @@ static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
854
1258
  *
855
1259
  * Set the +property+ to +value+
856
1260
  */
857
- static VALUE set(VALUE self, VALUE property, VALUE value)
1261
+ static VALUE
1262
+ set(VALUE self, VALUE property, VALUE value)
858
1263
  {
859
1264
  xmlNodePtr node, cur;
860
1265
  xmlAttrPtr prop;
861
- Data_Get_Struct(self, xmlNode, node);
1266
+ Noko_Node_Get_Struct(self, xmlNode, node);
862
1267
 
863
1268
  /* If a matching attribute node already exists, then xmlSetProp will destroy
864
1269
  * the existing node's children. However, if Nokogiri has a node object
@@ -867,13 +1272,13 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
867
1272
  * We can avoid this by unlinking these nodes first.
868
1273
  */
869
1274
  if (node->type != XML_ELEMENT_NODE) {
870
- return(Qnil);
1275
+ return (Qnil);
871
1276
  }
872
1277
  prop = xmlHasProp(node, (xmlChar *)StringValueCStr(property));
873
1278
  if (prop && prop->children) {
874
1279
  for (cur = prop->children; cur; cur = cur->next) {
875
1280
  if (cur->_private) {
876
- nokogiri_root_node(cur);
1281
+ noko_xml_document_pin_node(cur);
877
1282
  xmlUnlinkNode(cur);
878
1283
  }
879
1284
  }
@@ -891,7 +1296,8 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
891
1296
  *
892
1297
  * Get the value for +attribute+
893
1298
  */
894
- static VALUE get(VALUE self, VALUE rattribute)
1299
+ static VALUE
1300
+ get(VALUE self, VALUE rattribute)
895
1301
  {
896
1302
  xmlNodePtr node;
897
1303
  xmlChar *value = 0;
@@ -902,10 +1308,10 @@ static VALUE get(VALUE self, VALUE rattribute)
902
1308
 
903
1309
  if (NIL_P(rattribute)) { return Qnil; }
904
1310
 
905
- Data_Get_Struct(self, xmlNode, node);
1311
+ Noko_Node_Get_Struct(self, xmlNode, node);
906
1312
  attribute = xmlCharStrdup(StringValueCStr(rattribute));
907
1313
 
908
- colon = (xmlChar *)(uintptr_t)xmlStrchr(attribute, (const xmlChar)':');
1314
+ colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
909
1315
  if (colon) {
910
1316
  /* split the attribute string into separate prefix and name by
911
1317
  * null-terminating the prefix at the colon */
@@ -917,7 +1323,7 @@ static VALUE get(VALUE self, VALUE rattribute)
917
1323
  if (ns) {
918
1324
  value = xmlGetNsProp(node, attr_name, ns->href);
919
1325
  } else {
920
- value = xmlGetProp(node, (xmlChar*)StringValueCStr(rattribute));
1326
+ value = xmlGetProp(node, (xmlChar *)StringValueCStr(rattribute));
921
1327
  }
922
1328
  } else {
923
1329
  value = xmlGetNoNsProp(node, attribute);
@@ -938,15 +1344,16 @@ static VALUE get(VALUE self, VALUE rattribute)
938
1344
  *
939
1345
  * Set the namespace to +namespace+
940
1346
  */
941
- static VALUE set_namespace(VALUE self, VALUE namespace)
1347
+ static VALUE
1348
+ set_namespace(VALUE self, VALUE namespace)
942
1349
  {
943
1350
  xmlNodePtr node;
944
1351
  xmlNsPtr ns = NULL;
945
1352
 
946
- Data_Get_Struct(self, xmlNode, node);
1353
+ Noko_Node_Get_Struct(self, xmlNode, node);
947
1354
 
948
- if(!NIL_P(namespace)) {
949
- Data_Get_Struct(namespace, xmlNs, ns);
1355
+ if (!NIL_P(namespace)) {
1356
+ Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
950
1357
  }
951
1358
 
952
1359
  xmlSetNs(node, ns);
@@ -955,138 +1362,140 @@ static VALUE set_namespace(VALUE self, VALUE namespace)
955
1362
  }
956
1363
 
957
1364
  /*
958
- * call-seq:
959
- * attribute(name)
1365
+ * :call-seq:
1366
+ * namespace() → Namespace
960
1367
  *
961
- * Get the attribute node with +name+
962
- */
963
- static VALUE attr(VALUE self, VALUE name)
964
- {
965
- xmlNodePtr node;
966
- xmlAttrPtr prop;
967
- Data_Get_Struct(self, xmlNode, node);
968
- prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
969
-
970
- if(! prop) { return Qnil; }
971
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
972
- }
973
-
974
- /*
975
- * call-seq:
976
- * attribute_with_ns(name, namespace)
1368
+ * [Returns] The Namespace of the element or attribute node, or +nil+ if there is no namespace.
977
1369
  *
978
- * Get the attribute node with +name+ and +namespace+
979
- */
980
- static VALUE attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
981
- {
982
- xmlNodePtr node;
983
- xmlAttrPtr prop;
984
- Data_Get_Struct(self, xmlNode, node);
985
- prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
986
- NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
987
-
988
- if(! prop) { return Qnil; }
989
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
990
- }
991
-
992
- /*
993
- * call-seq:
994
- * attribute_nodes()
1370
+ * *Example:*
995
1371
  *
996
- * returns a list containing the Node attributes.
1372
+ * doc = Nokogiri::XML(<<~EOF)
1373
+ * <root>
1374
+ * <first/>
1375
+ * <second xmlns="http://example.com/child"/>
1376
+ * <foo:third xmlns:foo="http://example.com/foo"/>
1377
+ * </root>
1378
+ * EOF
1379
+ * doc.at_xpath("//first").namespace
1380
+ * # => nil
1381
+ * doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace
1382
+ * # => #(Namespace:0x3c { href = "http://example.com/child" })
1383
+ * doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace
1384
+ * # => #(Namespace:0x50 { prefix = "foo", href = "http://example.com/foo" })
997
1385
  */
998
- static VALUE attribute_nodes(VALUE self)
1386
+ static VALUE
1387
+ rb_xml_node_namespace(VALUE rb_node)
999
1388
  {
1000
- /* this code in the mode of xmlHasProp() */
1001
- xmlNodePtr node;
1002
- VALUE attr;
1003
-
1004
- Data_Get_Struct(self, xmlNode, node);
1389
+ xmlNodePtr c_node ;
1390
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1005
1391
 
1006
- attr = rb_ary_new();
1007
- Nokogiri_xml_node_properties(node, attr);
1392
+ if (c_node->ns) {
1393
+ return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
1394
+ }
1008
1395
 
1009
- return attr ;
1396
+ return Qnil ;
1010
1397
  }
1011
1398
 
1012
-
1013
1399
  /*
1014
- * call-seq:
1015
- * namespace()
1400
+ * :call-seq:
1401
+ * namespace_definitions() → Array<Nokogiri::XML::Namespace>
1016
1402
  *
1017
- * returns the namespace of the element or attribute node as a Namespace
1018
- * object, or nil if there is no namespace for the element or attribute.
1019
- */
1020
- static VALUE namespace(VALUE self)
1021
- {
1022
- xmlNodePtr node ;
1023
- Data_Get_Struct(self, xmlNode, node);
1024
-
1025
- if (node->ns) {
1026
- return Nokogiri_wrap_xml_namespace(node->doc, node->ns);
1027
- }
1028
-
1029
- return Qnil ;
1030
- }
1031
-
1032
- /*
1033
- * call-seq:
1034
- * namespace_definitions()
1403
+ * [Returns]
1404
+ * Namespaces that are defined directly on this node, as an Array of Namespace objects. The array
1405
+ * will be empty if no namespaces are defined on this node.
1035
1406
  *
1036
- * returns namespaces defined on self element directly, as an array of Namespace objects. Includes both a default namespace (as in"xmlns="), and prefixed namespaces (as in "xmlns:prefix=").
1407
+ * *Example:*
1408
+ *
1409
+ * doc = Nokogiri::XML(<<~EOF)
1410
+ * <root xmlns="http://example.com/root">
1411
+ * <first/>
1412
+ * <second xmlns="http://example.com/child" xmlns:unused="http://example.com/unused"/>
1413
+ * <foo:third xmlns:foo="http://example.com/foo"/>
1414
+ * </root>
1415
+ * EOF
1416
+ * doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_definitions
1417
+ * # => []
1418
+ * doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace_definitions
1419
+ * # => [#(Namespace:0x3c { href = "http://example.com/child" }),
1420
+ * # #(Namespace:0x50 {
1421
+ * # prefix = "unused",
1422
+ * # href = "http://example.com/unused"
1423
+ * # })]
1424
+ * doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace_definitions
1425
+ * # => [#(Namespace:0x64 { prefix = "foo", href = "http://example.com/foo" })]
1037
1426
  */
1038
- static VALUE namespace_definitions(VALUE self)
1427
+ static VALUE
1428
+ namespace_definitions(VALUE rb_node)
1039
1429
  {
1040
1430
  /* this code in the mode of xmlHasProp() */
1041
- xmlNodePtr node ;
1042
- VALUE list;
1043
- xmlNsPtr ns;
1044
-
1045
- Data_Get_Struct(self, xmlNode, node);
1431
+ xmlNodePtr c_node ;
1432
+ xmlNsPtr c_namespace;
1433
+ VALUE definitions = rb_ary_new();
1046
1434
 
1047
- list = rb_ary_new();
1435
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1048
1436
 
1049
- ns = node->nsDef;
1050
-
1051
- if(!ns) { return list; }
1437
+ c_namespace = c_node->nsDef;
1438
+ if (!c_namespace) {
1439
+ return definitions;
1440
+ }
1052
1441
 
1053
- while(NULL != ns) {
1054
- rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns));
1055
- ns = ns->next;
1442
+ while (c_namespace != NULL) {
1443
+ rb_ary_push(definitions, noko_xml_namespace_wrap(c_namespace, c_node->doc));
1444
+ c_namespace = c_namespace->next;
1056
1445
  }
1057
1446
 
1058
- return list;
1447
+ return definitions;
1059
1448
  }
1060
1449
 
1061
1450
  /*
1062
- * call-seq:
1063
- * namespace_scopes()
1451
+ * :call-seq:
1452
+ * namespace_scopes() → Array<Nokogiri::XML::Namespace>
1453
+ *
1454
+ * [Returns] Array of all the Namespaces on this node and its ancestors.
1064
1455
  *
1065
- * returns namespaces in scope for self -- those defined on self element
1066
- * directly or any ancestor node -- as an array of Namespace objects. Default
1067
- * namespaces ("xmlns=" style) for self are included in this array; Default
1068
- * namespaces for ancestors, however, are not. See also #namespaces
1456
+ * See also #namespaces
1457
+ *
1458
+ * *Example:*
1459
+ *
1460
+ * doc = Nokogiri::XML(<<~EOF)
1461
+ * <root xmlns="http://example.com/root" xmlns:bar="http://example.com/bar">
1462
+ * <first/>
1463
+ * <second xmlns="http://example.com/child"/>
1464
+ * <third xmlns:foo="http://example.com/foo"/>
1465
+ * </root>
1466
+ * EOF
1467
+ * doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_scopes
1468
+ * # => [#(Namespace:0x3c { href = "http://example.com/root" }),
1469
+ * # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
1470
+ * doc.at_xpath("//child:second", "child" => "http://example.com/child").namespace_scopes
1471
+ * # => [#(Namespace:0x64 { href = "http://example.com/child" }),
1472
+ * # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
1473
+ * doc.at_xpath("//root:third", "root" => "http://example.com/root").namespace_scopes
1474
+ * # => [#(Namespace:0x78 { prefix = "foo", href = "http://example.com/foo" }),
1475
+ * # #(Namespace:0x3c { href = "http://example.com/root" }),
1476
+ * # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
1069
1477
  */
1070
- static VALUE namespace_scopes(VALUE self)
1478
+ static VALUE
1479
+ rb_xml_node_namespace_scopes(VALUE rb_node)
1071
1480
  {
1072
- xmlNodePtr node ;
1073
- VALUE list;
1074
- xmlNsPtr *ns_list;
1481
+ xmlNodePtr c_node ;
1482
+ xmlNsPtr *namespaces;
1483
+ VALUE scopes = rb_ary_new();
1075
1484
  int j;
1076
1485
 
1077
- Data_Get_Struct(self, xmlNode, node);
1486
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1078
1487
 
1079
- list = rb_ary_new();
1080
- ns_list = xmlGetNsList(node->doc, node);
1081
-
1082
- if(!ns_list) { return list; }
1488
+ namespaces = xmlGetNsList(c_node->doc, c_node);
1489
+ if (!namespaces) {
1490
+ return scopes;
1491
+ }
1083
1492
 
1084
- for (j = 0 ; ns_list[j] != NULL ; ++j) {
1085
- rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns_list[j]));
1493
+ for (j = 0 ; namespaces[j] != NULL ; ++j) {
1494
+ rb_ary_push(scopes, noko_xml_namespace_wrap(namespaces[j], c_node->doc));
1086
1495
  }
1087
1496
 
1088
- xmlFree(ns_list);
1089
- return list;
1497
+ xmlFree(namespaces);
1498
+ return scopes;
1090
1499
  }
1091
1500
 
1092
1501
  /*
@@ -1095,10 +1504,11 @@ static VALUE namespace_scopes(VALUE self)
1095
1504
  *
1096
1505
  * Get the type for this Node
1097
1506
  */
1098
- static VALUE node_type(VALUE self)
1507
+ static VALUE
1508
+ node_type(VALUE self)
1099
1509
  {
1100
1510
  xmlNodePtr node;
1101
- Data_Get_Struct(self, xmlNode, node);
1511
+ Noko_Node_Get_Struct(self, xmlNode, node);
1102
1512
  return INT2NUM((long)node->type);
1103
1513
  }
1104
1514
 
@@ -1108,16 +1518,17 @@ static VALUE node_type(VALUE self)
1108
1518
  *
1109
1519
  * Set the content for this Node
1110
1520
  */
1111
- static VALUE set_native_content(VALUE self, VALUE content)
1521
+ static VALUE
1522
+ set_native_content(VALUE self, VALUE content)
1112
1523
  {
1113
1524
  xmlNodePtr node, child, next ;
1114
- Data_Get_Struct(self, xmlNode, node);
1525
+ Noko_Node_Get_Struct(self, xmlNode, node);
1115
1526
 
1116
1527
  child = node->children;
1117
1528
  while (NULL != child) {
1118
1529
  next = child->next ;
1119
1530
  xmlUnlinkNode(child) ;
1120
- nokogiri_root_node(child);
1531
+ noko_xml_document_pin_node(child);
1121
1532
  child = next ;
1122
1533
  }
1123
1534
 
@@ -1125,42 +1536,20 @@ static VALUE set_native_content(VALUE self, VALUE content)
1125
1536
  return content;
1126
1537
  }
1127
1538
 
1128
- /*
1129
- * call-seq:
1130
- * content
1131
- *
1132
- * Returns the plaintext content for this Node. Note that entities will always
1133
- * be expanded in the returned string.
1134
- */
1135
- static VALUE get_native_content(VALUE self)
1136
- {
1137
- xmlNodePtr node;
1138
- xmlChar * content;
1139
-
1140
- Data_Get_Struct(self, xmlNode, node);
1141
-
1142
- content = xmlNodeGetContent(node);
1143
- if(content) {
1144
- VALUE rval = NOKOGIRI_STR_NEW2(content);
1145
- xmlFree(content);
1146
- return rval;
1147
- }
1148
- return Qnil;
1149
- }
1150
-
1151
1539
  /*
1152
1540
  * call-seq:
1153
1541
  * lang=
1154
1542
  *
1155
1543
  * Set the language of a node, i.e. the values of the xml:lang attribute.
1156
1544
  */
1157
- static VALUE set_lang(VALUE self_rb, VALUE lang_rb)
1545
+ static VALUE
1546
+ set_lang(VALUE self_rb, VALUE lang_rb)
1158
1547
  {
1159
1548
  xmlNodePtr self ;
1160
- xmlChar* lang ;
1549
+ xmlChar *lang ;
1161
1550
 
1162
- Data_Get_Struct(self_rb, xmlNode, self);
1163
- lang = (xmlChar*)StringValueCStr(lang_rb);
1551
+ Noko_Node_Get_Struct(self_rb, xmlNode, self);
1552
+ lang = (xmlChar *)StringValueCStr(lang_rb);
1164
1553
 
1165
1554
  xmlNodeSetLang(self, lang);
1166
1555
 
@@ -1174,13 +1563,14 @@ static VALUE set_lang(VALUE self_rb, VALUE lang_rb)
1174
1563
  * Searches the language of a node, i.e. the values of the xml:lang attribute or
1175
1564
  * the one carried by the nearest ancestor.
1176
1565
  */
1177
- static VALUE get_lang(VALUE self_rb)
1566
+ static VALUE
1567
+ get_lang(VALUE self_rb)
1178
1568
  {
1179
1569
  xmlNodePtr self ;
1180
- xmlChar* lang ;
1570
+ xmlChar *lang ;
1181
1571
  VALUE lang_rb ;
1182
1572
 
1183
- Data_Get_Struct(self_rb, xmlNode, self);
1573
+ Noko_Node_Get_Struct(self_rb, xmlNode, self);
1184
1574
 
1185
1575
  lang = xmlNodeGetLang(self);
1186
1576
  if (lang) {
@@ -1193,7 +1583,8 @@ static VALUE get_lang(VALUE self_rb)
1193
1583
  }
1194
1584
 
1195
1585
  /* :nodoc: */
1196
- static VALUE add_child(VALUE self, VALUE new_child)
1586
+ static VALUE
1587
+ add_child(VALUE self, VALUE new_child)
1197
1588
  {
1198
1589
  return reparent_node_with(self, new_child, xmlAddChild);
1199
1590
  }
@@ -1204,15 +1595,16 @@ static VALUE add_child(VALUE self, VALUE new_child)
1204
1595
  *
1205
1596
  * Get the parent Node for this Node
1206
1597
  */
1207
- static VALUE get_parent(VALUE self)
1598
+ static VALUE
1599
+ get_parent(VALUE self)
1208
1600
  {
1209
1601
  xmlNodePtr node, parent;
1210
- Data_Get_Struct(self, xmlNode, node);
1602
+ Noko_Node_Get_Struct(self, xmlNode, node);
1211
1603
 
1212
1604
  parent = node->parent;
1213
- if(!parent) { return Qnil; }
1605
+ if (!parent) { return Qnil; }
1214
1606
 
1215
- return Nokogiri_wrap_xml_node(Qnil, parent) ;
1607
+ return noko_xml_node_wrap(Qnil, parent) ;
1216
1608
  }
1217
1609
 
1218
1610
  /*
@@ -1221,11 +1613,12 @@ static VALUE get_parent(VALUE self)
1221
1613
  *
1222
1614
  * Set the name for this Node
1223
1615
  */
1224
- static VALUE set_name(VALUE self, VALUE new_name)
1616
+ static VALUE
1617
+ set_name(VALUE self, VALUE new_name)
1225
1618
  {
1226
1619
  xmlNodePtr node;
1227
- Data_Get_Struct(self, xmlNode, node);
1228
- xmlNodeSetName(node, (xmlChar*)StringValueCStr(new_name));
1620
+ Noko_Node_Get_Struct(self, xmlNode, node);
1621
+ xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
1229
1622
  return new_name;
1230
1623
  }
1231
1624
 
@@ -1235,11 +1628,12 @@ static VALUE set_name(VALUE self, VALUE new_name)
1235
1628
  *
1236
1629
  * Returns the name for this Node
1237
1630
  */
1238
- static VALUE get_name(VALUE self)
1631
+ static VALUE
1632
+ get_name(VALUE self)
1239
1633
  {
1240
1634
  xmlNodePtr node;
1241
- Data_Get_Struct(self, xmlNode, node);
1242
- if(node->name) {
1635
+ Noko_Node_Get_Struct(self, xmlNode, node);
1636
+ if (node->name) {
1243
1637
  return NOKOGIRI_STR_NEW2(node->name);
1244
1638
  }
1245
1639
  return Qnil;
@@ -1251,28 +1645,39 @@ static VALUE get_name(VALUE self)
1251
1645
  *
1252
1646
  * Returns the path associated with this Node
1253
1647
  */
1254
- static VALUE path(VALUE self)
1648
+ static VALUE
1649
+ rb_xml_node_path(VALUE rb_node)
1255
1650
  {
1256
- xmlNodePtr node;
1257
- xmlChar *path ;
1651
+ xmlNodePtr c_node;
1652
+ xmlChar *c_path ;
1258
1653
  VALUE rval;
1259
1654
 
1260
- Data_Get_Struct(self, xmlNode, node);
1655
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1656
+
1657
+ c_path = xmlGetNodePath(c_node);
1658
+ if (c_path == NULL) {
1659
+ // see https://github.com/sparklemotion/nokogiri/issues/2250
1660
+ // this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
1661
+ // do this for now to preserve the behavior across libxml2 versions.
1662
+ rval = NOKOGIRI_STR_NEW2("?");
1663
+ } else {
1664
+ rval = NOKOGIRI_STR_NEW2(c_path);
1665
+ xmlFree(c_path);
1666
+ }
1261
1667
 
1262
- path = xmlGetNodePath(node);
1263
- rval = NOKOGIRI_STR_NEW2(path);
1264
- xmlFree(path);
1265
1668
  return rval ;
1266
1669
  }
1267
1670
 
1268
1671
  /* :nodoc: */
1269
- static VALUE add_next_sibling(VALUE self, VALUE new_sibling)
1672
+ static VALUE
1673
+ add_next_sibling(VALUE self, VALUE new_sibling)
1270
1674
  {
1271
1675
  return reparent_node_with(self, new_sibling, xmlAddNextSibling) ;
1272
1676
  }
1273
1677
 
1274
1678
  /* :nodoc: */
1275
- static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
1679
+ static VALUE
1680
+ add_previous_sibling(VALUE self, VALUE new_sibling)
1276
1681
  {
1277
1682
  return reparent_node_with(self, new_sibling, xmlAddPrevSibling) ;
1278
1683
  }
@@ -1283,7 +1688,8 @@ static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
1283
1688
  *
1284
1689
  * Write this Node to +io+ with +encoding+ and +options+
1285
1690
  */
1286
- static VALUE native_write_to(
1691
+ static VALUE
1692
+ native_write_to(
1287
1693
  VALUE self,
1288
1694
  VALUE io,
1289
1695
  VALUE encoding,
@@ -1292,10 +1698,10 @@ static VALUE native_write_to(
1292
1698
  )
1293
1699
  {
1294
1700
  xmlNodePtr node;
1295
- const char * before_indent;
1701
+ const char *before_indent;
1296
1702
  xmlSaveCtxtPtr savectx;
1297
1703
 
1298
- Data_Get_Struct(self, xmlNode, node);
1704
+ Noko_Node_Get_Struct(self, xmlNode, node);
1299
1705
 
1300
1706
  xmlIndentTreeOutput = 1;
1301
1707
 
@@ -1304,8 +1710,8 @@ static VALUE native_write_to(
1304
1710
  xmlTreeIndentString = StringValueCStr(indent_string);
1305
1711
 
1306
1712
  savectx = xmlSaveToIO(
1307
- (xmlOutputWriteCallback)io_write_callback,
1308
- (xmlOutputCloseCallback)io_close_callback,
1713
+ (xmlOutputWriteCallback)noko_io_write,
1714
+ (xmlOutputCloseCallback)noko_io_close,
1309
1715
  (void *)io,
1310
1716
  RTEST(encoding) ? StringValueCStr(encoding) : NULL,
1311
1717
  (int)NUM2INT(options)
@@ -1319,92 +1725,102 @@ static VALUE native_write_to(
1319
1725
  }
1320
1726
 
1321
1727
  /*
1322
- * call-seq:
1323
- * line
1728
+ * :call-seq:
1729
+ * line() → Integer
1324
1730
  *
1325
- * Returns the line for this Node
1731
+ * [Returns] The line number of this Node.
1732
+ *
1733
+ * ---
1734
+ *
1735
+ * <b> ⚠ The CRuby and JRuby implementations differ in important ways! </b>
1736
+ *
1737
+ * Semantic differences:
1738
+ * - The CRuby method reflects the node's line number <i>in the parsed string</i>
1739
+ * - The JRuby method reflects the node's line number <i>in the final DOM structure</i> after
1740
+ * corrections have been applied
1741
+ *
1742
+ * Performance differences:
1743
+ * - The CRuby method is {O(1)}[https://en.wikipedia.org/wiki/Time_complexity#Constant_time]
1744
+ * (constant time)
1745
+ * - The JRuby method is {O(n)}[https://en.wikipedia.org/wiki/Time_complexity#Linear_time] (linear
1746
+ * time, where n is the number of nodes before/above the element in the DOM)
1747
+ *
1748
+ * If you'd like to help improve the JRuby implementation, please review these issues and reach out
1749
+ * to the maintainers:
1750
+ * - https://github.com/sparklemotion/nokogiri/issues/1223
1751
+ * - https://github.com/sparklemotion/nokogiri/pull/2177
1752
+ * - https://github.com/sparklemotion/nokogiri/issues/2380
1326
1753
  */
1327
- static VALUE line(VALUE self)
1754
+ static VALUE
1755
+ rb_xml_node_line(VALUE rb_node)
1328
1756
  {
1329
- xmlNodePtr node;
1330
- Data_Get_Struct(self, xmlNode, node);
1757
+ xmlNodePtr c_node;
1758
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1331
1759
 
1332
- return INT2NUM(xmlGetLineNo(node));
1760
+ return INT2NUM(xmlGetLineNo(c_node));
1333
1761
  }
1334
1762
 
1335
1763
  /*
1336
1764
  * call-seq:
1337
- * add_namespace_definition(prefix, href)
1338
- *
1339
- * Adds a namespace definition with +prefix+ using +href+ value. The result is
1340
- * as if parsed XML for this node had included an attribute
1341
- * 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
1342
- * added by passing 'nil' for prefix. Namespaces added this way will not
1343
- * show up in #attributes, but they will be included as an xmlns attribute
1344
- * when the node is serialized to XML.
1765
+ * line=(num)
1766
+ *
1767
+ * Sets the line for this Node. num must be less than 65535.
1345
1768
  */
1346
- static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
1769
+ static VALUE
1770
+ rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
1347
1771
  {
1348
- xmlNodePtr node, namespace;
1349
- xmlNsPtr ns;
1772
+ xmlNodePtr c_node;
1773
+ int line_number = NUM2INT(rb_line_number);
1350
1774
 
1351
- Data_Get_Struct(self, xmlNode, node);
1352
- namespace = node ;
1775
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1353
1776
 
1354
- ns = xmlSearchNs(
1355
- node->doc,
1356
- node,
1357
- (const xmlChar *)(NIL_P(prefix) ? NULL : StringValueCStr(prefix))
1358
- );
1359
-
1360
- if(!ns) {
1361
- if (node->type != XML_ELEMENT_NODE) {
1362
- namespace = node->parent;
1777
+ // libxml2 optionally uses xmlNode.psvi to store longer line numbers, but only for text nodes.
1778
+ // search for "psvi" in SAX2.c and tree.c to learn more.
1779
+ if (line_number < 65535) {
1780
+ c_node->line = (short) line_number;
1781
+ } else {
1782
+ c_node->line = 65535;
1783
+ if (c_node->type == XML_TEXT_NODE) {
1784
+ c_node->psvi = (void *)(ptrdiff_t) line_number;
1363
1785
  }
1364
- ns = xmlNewNs(
1365
- namespace,
1366
- (const xmlChar *)StringValueCStr(href),
1367
- (const xmlChar *)(NIL_P(prefix) ? NULL : StringValueCStr(prefix))
1368
- );
1369
1786
  }
1370
1787
 
1371
- if (!ns) { return Qnil ; }
1372
-
1373
- if(NIL_P(prefix) || node != namespace) { xmlSetNs(node, ns); }
1374
-
1375
- return Nokogiri_wrap_xml_namespace(node->doc, ns);
1788
+ return rb_line_number;
1376
1789
  }
1377
1790
 
1378
- /*
1379
- * call-seq:
1380
- * new(name, document)
1381
- *
1382
- * Create a new node with +name+ sharing GC lifecycle with +document+
1383
- */
1384
- static VALUE new(int argc, VALUE *argv, VALUE klass)
1791
+ /* :nodoc: documented in lib/nokogiri/xml/node.rb */
1792
+ static VALUE
1793
+ rb_xml_node_new(int argc, VALUE *argv, VALUE klass)
1385
1794
  {
1386
- xmlDocPtr doc;
1387
- xmlNodePtr node;
1388
- VALUE name;
1389
- VALUE document;
1795
+ xmlNodePtr c_document_node;
1796
+ xmlNodePtr c_node;
1797
+ VALUE rb_name;
1798
+ VALUE rb_document_node;
1390
1799
  VALUE rest;
1391
1800
  VALUE rb_node;
1392
1801
 
1393
- rb_scan_args(argc, argv, "2*", &name, &document, &rest);
1802
+ rb_scan_args(argc, argv, "2*", &rb_name, &rb_document_node, &rest);
1394
1803
 
1395
- Data_Get_Struct(document, xmlDoc, doc);
1804
+ if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlNode)) {
1805
+ rb_raise(rb_eArgError, "document must be a Nokogiri::XML::Node");
1806
+ }
1807
+ if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlDocument)) {
1808
+ // TODO: deprecate allowing Node
1809
+ NOKO_WARN_DEPRECATION("Passing a Node as the second parameter to Node.new is deprecated. Please pass a Document instead, or prefer an alternative constructor like Node#add_child. This will become an error in a future release of Nokogiri.");
1810
+ }
1811
+ Noko_Node_Get_Struct(rb_document_node, xmlNode, c_document_node);
1396
1812
 
1397
- node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(name));
1398
- node->doc = doc->doc;
1399
- nokogiri_root_node(node);
1813
+ c_node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(rb_name));
1814
+ c_node->doc = c_document_node->doc;
1815
+ noko_xml_document_pin_node(c_node);
1400
1816
 
1401
- rb_node = Nokogiri_wrap_xml_node(
1817
+ rb_node = noko_xml_node_wrap(
1402
1818
  klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1403
- node
1819
+ c_node
1404
1820
  );
1405
1821
  rb_obj_call_init(rb_node, argc, argv);
1406
1822
 
1407
- if(rb_block_given_p()) { rb_yield(rb_node); }
1823
+ if (rb_block_given_p()) { rb_yield(rb_node); }
1408
1824
 
1409
1825
  return rb_node;
1410
1826
  }
@@ -1415,13 +1831,14 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
1415
1831
  *
1416
1832
  * Returns the Node as html.
1417
1833
  */
1418
- static VALUE dump_html(VALUE self)
1834
+ static VALUE
1835
+ dump_html(VALUE self)
1419
1836
  {
1420
1837
  xmlBufferPtr buf ;
1421
1838
  xmlNodePtr node ;
1422
1839
  VALUE html;
1423
1840
 
1424
- Data_Get_Struct(self, xmlNode, node);
1841
+ Noko_Node_Get_Struct(self, xmlNode, node);
1425
1842
 
1426
1843
  buf = xmlBufferCreate() ;
1427
1844
  htmlNodeDump(buf, node->doc, node);
@@ -1436,11 +1853,12 @@ static VALUE dump_html(VALUE self)
1436
1853
  *
1437
1854
  * Compare this Node to +other+ with respect to their Document
1438
1855
  */
1439
- static VALUE compare(VALUE self, VALUE _other)
1856
+ static VALUE
1857
+ compare(VALUE self, VALUE _other)
1440
1858
  {
1441
1859
  xmlNodePtr node, other;
1442
- Data_Get_Struct(self, xmlNode, node);
1443
- Data_Get_Struct(_other, xmlNode, other);
1860
+ Noko_Node_Get_Struct(self, xmlNode, node);
1861
+ Noko_Node_Get_Struct(_other, xmlNode, other);
1444
1862
 
1445
1863
  return INT2NUM((long)xmlXPathCmpNodes(other, node));
1446
1864
  }
@@ -1453,13 +1871,14 @@ static VALUE compare(VALUE self, VALUE _other)
1453
1871
  * Loads and substitutes all xinclude elements below the node. The
1454
1872
  * parser context will be initialized with +options+.
1455
1873
  */
1456
- static VALUE process_xincludes(VALUE self, VALUE options)
1874
+ static VALUE
1875
+ process_xincludes(VALUE self, VALUE options)
1457
1876
  {
1458
1877
  int rcode ;
1459
1878
  xmlNodePtr node;
1460
1879
  VALUE error_list = rb_ary_new();
1461
1880
 
1462
- Data_Get_Struct(self, xmlNode, node);
1881
+ Noko_Node_Get_Struct(self, xmlNode, node);
1463
1882
 
1464
1883
  xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
1465
1884
  rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
@@ -1469,7 +1888,7 @@ static VALUE process_xincludes(VALUE self, VALUE options)
1469
1888
  xmlErrorPtr error;
1470
1889
 
1471
1890
  error = xmlGetLastError();
1472
- if(error) {
1891
+ if (error) {
1473
1892
  rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
1474
1893
  } else {
1475
1894
  rb_raise(rb_eRuntimeError, "Could not perform xinclude substitution");
@@ -1481,7 +1900,8 @@ static VALUE process_xincludes(VALUE self, VALUE options)
1481
1900
 
1482
1901
 
1483
1902
  /* TODO: DOCUMENT ME */
1484
- static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1903
+ static VALUE
1904
+ in_context(VALUE self, VALUE _str, VALUE _options)
1485
1905
  {
1486
1906
  xmlNodePtr node, list = 0, tmp, child_iter, node_children, doc_children;
1487
1907
  xmlNodeSetPtr set;
@@ -1489,7 +1909,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1489
1909
  VALUE doc, err;
1490
1910
  int doc_is_empty;
1491
1911
 
1492
- Data_Get_Struct(self, xmlNode, node);
1912
+ Noko_Node_Get_Struct(self, xmlNode, node);
1493
1913
 
1494
1914
  doc = DOC_RUBY_OBJECT(node->doc);
1495
1915
  err = rb_iv_get(doc, "@errors");
@@ -1530,9 +1950,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1530
1950
  */
1531
1951
  child_iter = node->doc->children ;
1532
1952
  while (child_iter) {
1533
- if (child_iter->parent != (xmlNodePtr)node->doc) {
1534
- child_iter->parent = (xmlNodePtr)node->doc;
1535
- }
1953
+ child_iter->parent = (xmlNodePtr)node->doc;
1536
1954
  child_iter = child_iter->next;
1537
1955
  }
1538
1956
 
@@ -1562,12 +1980,12 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1562
1980
 
1563
1981
  /* FIXME: This probably needs to handle more constants... */
1564
1982
  switch (error) {
1565
- case XML_ERR_INTERNAL_ERROR:
1566
- case XML_ERR_NO_MEMORY:
1567
- rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
1568
- break;
1569
- default:
1570
- break;
1983
+ case XML_ERR_INTERNAL_ERROR:
1984
+ case XML_ERR_NO_MEMORY:
1985
+ rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
1986
+ break;
1987
+ default:
1988
+ break;
1571
1989
  }
1572
1990
 
1573
1991
  set = xmlXPathNodeSetCreate(NULL);
@@ -1576,178 +1994,172 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1576
1994
  tmp = list->next;
1577
1995
  list->next = NULL;
1578
1996
  xmlXPathNodeSetAddUnique(set, list);
1579
- nokogiri_root_node(list);
1997
+ noko_xml_document_pin_node(list);
1580
1998
  list = tmp;
1581
1999
  }
1582
2000
 
1583
- return Nokogiri_wrap_xml_node_set(set, doc);
2001
+ return noko_xml_node_set_wrap(set, doc);
1584
2002
  }
1585
2003
 
1586
-
1587
- VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node)
2004
+ VALUE
2005
+ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1588
2006
  {
1589
- VALUE document = Qnil ;
1590
- VALUE node_cache = Qnil ;
1591
- VALUE rb_node = Qnil ;
2007
+ VALUE rb_document, rb_node_cache, rb_node;
1592
2008
  nokogiriTuplePtr node_has_a_document;
1593
- xmlDocPtr doc;
1594
- void (*mark_method)(xmlNodePtr) = NULL ;
2009
+ xmlDocPtr c_doc;
1595
2010
 
1596
- assert(node);
2011
+ assert(c_node);
1597
2012
 
1598
- if(node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE) {
1599
- return DOC_RUBY_OBJECT(node->doc);
2013
+ if (c_node->type == XML_DOCUMENT_NODE || c_node->type == XML_HTML_DOCUMENT_NODE) {
2014
+ return DOC_RUBY_OBJECT(c_node->doc);
1600
2015
  }
1601
2016
 
1602
- /* It's OK if the node doesn't have a fully-realized document (as in XML::Reader). */
1603
- /* see https://github.com/sparklemotion/nokogiri/issues/95 */
1604
- /* and https://github.com/sparklemotion/nokogiri/issues/439 */
1605
- doc = node->doc;
1606
- if (doc->type == XML_DOCUMENT_FRAG_NODE) { doc = doc->doc; }
1607
- node_has_a_document = DOC_RUBY_OBJECT_TEST(doc);
2017
+ c_doc = c_node->doc;
2018
+
2019
+ // Nodes yielded from XML::Reader don't have a fully-realized Document
2020
+ node_has_a_document = DOC_RUBY_OBJECT_TEST(c_doc);
1608
2021
 
1609
- if(node->_private && node_has_a_document) {
1610
- return (VALUE)node->_private;
2022
+ if (c_node->_private && node_has_a_document) {
2023
+ return (VALUE)c_node->_private;
1611
2024
  }
1612
2025
 
1613
- if(!RTEST(klass)) {
1614
- switch(node->type) {
1615
- case XML_ELEMENT_NODE:
1616
- klass = cNokogiriXmlElement;
1617
- break;
1618
- case XML_TEXT_NODE:
1619
- klass = cNokogiriXmlText;
1620
- break;
1621
- case XML_ATTRIBUTE_NODE:
1622
- klass = cNokogiriXmlAttr;
1623
- break;
1624
- case XML_ENTITY_REF_NODE:
1625
- klass = cNokogiriXmlEntityReference;
1626
- break;
1627
- case XML_COMMENT_NODE:
1628
- klass = cNokogiriXmlComment;
1629
- break;
1630
- case XML_DOCUMENT_FRAG_NODE:
1631
- klass = cNokogiriXmlDocumentFragment;
1632
- break;
1633
- case XML_PI_NODE:
1634
- klass = cNokogiriXmlProcessingInstruction;
1635
- break;
1636
- case XML_ENTITY_DECL:
1637
- klass = cNokogiriXmlEntityDecl;
1638
- break;
1639
- case XML_CDATA_SECTION_NODE:
1640
- klass = cNokogiriXmlCData;
1641
- break;
1642
- case XML_DTD_NODE:
1643
- klass = cNokogiriXmlDtd;
1644
- break;
1645
- case XML_ATTRIBUTE_DECL:
1646
- klass = cNokogiriXmlAttributeDecl;
1647
- break;
1648
- case XML_ELEMENT_DECL:
1649
- klass = cNokogiriXmlElementDecl;
1650
- break;
1651
- default:
1652
- klass = cNokogiriXmlNode;
2026
+ if (!RTEST(rb_class)) {
2027
+ switch (c_node->type) {
2028
+ case XML_ELEMENT_NODE:
2029
+ rb_class = cNokogiriXmlElement;
2030
+ break;
2031
+ case XML_TEXT_NODE:
2032
+ rb_class = cNokogiriXmlText;
2033
+ break;
2034
+ case XML_ATTRIBUTE_NODE:
2035
+ rb_class = cNokogiriXmlAttr;
2036
+ break;
2037
+ case XML_ENTITY_REF_NODE:
2038
+ rb_class = cNokogiriXmlEntityReference;
2039
+ break;
2040
+ case XML_COMMENT_NODE:
2041
+ rb_class = cNokogiriXmlComment;
2042
+ break;
2043
+ case XML_DOCUMENT_FRAG_NODE:
2044
+ rb_class = cNokogiriXmlDocumentFragment;
2045
+ break;
2046
+ case XML_PI_NODE:
2047
+ rb_class = cNokogiriXmlProcessingInstruction;
2048
+ break;
2049
+ case XML_ENTITY_DECL:
2050
+ rb_class = cNokogiriXmlEntityDecl;
2051
+ break;
2052
+ case XML_CDATA_SECTION_NODE:
2053
+ rb_class = cNokogiriXmlCData;
2054
+ break;
2055
+ case XML_DTD_NODE:
2056
+ rb_class = cNokogiriXmlDtd;
2057
+ break;
2058
+ case XML_ATTRIBUTE_DECL:
2059
+ rb_class = cNokogiriXmlAttributeDecl;
2060
+ break;
2061
+ case XML_ELEMENT_DECL:
2062
+ rb_class = cNokogiriXmlElementDecl;
2063
+ break;
2064
+ default:
2065
+ rb_class = cNokogiriXmlNode;
1653
2066
  }
1654
2067
  }
1655
2068
 
1656
- mark_method = node_has_a_document ? mark : NULL ;
1657
-
1658
- rb_node = Data_Wrap_Struct(klass, mark_method, debug_node_dealloc, node) ;
1659
- node->_private = (void *)rb_node;
2069
+ rb_node = TypedData_Wrap_Struct(rb_class, &nokogiri_node_type, c_node) ;
2070
+ c_node->_private = (void *)rb_node;
1660
2071
 
1661
2072
  if (node_has_a_document) {
1662
- document = DOC_RUBY_OBJECT(doc);
1663
- node_cache = DOC_NODE_CACHE(doc);
1664
- rb_ary_push(node_cache, rb_node);
1665
- rb_funcall(document, decorate, 1, rb_node);
2073
+ rb_document = DOC_RUBY_OBJECT(c_doc);
2074
+ rb_node_cache = DOC_NODE_CACHE(c_doc);
2075
+ rb_ary_push(rb_node_cache, rb_node);
2076
+ rb_funcall(rb_document, id_decorate, 1, rb_node);
1666
2077
  }
1667
2078
 
1668
2079
  return rb_node ;
1669
2080
  }
1670
2081
 
1671
2082
 
1672
- void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_list)
2083
+ /*
2084
+ * return Array<Nokogiri::XML::Attr> containing the node's attributes
2085
+ */
2086
+ VALUE
2087
+ noko_xml_node_attrs(xmlNodePtr c_node)
1673
2088
  {
1674
- xmlAttrPtr prop;
1675
- prop = node->properties ;
1676
- while (prop != NULL) {
1677
- rb_ary_push(attr_list, Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop));
1678
- prop = prop->next ;
2089
+ VALUE rb_properties = rb_ary_new();
2090
+ xmlAttrPtr c_property;
2091
+
2092
+ c_property = c_node->properties ;
2093
+ while (c_property != NULL) {
2094
+ rb_ary_push(rb_properties, noko_xml_node_wrap(Qnil, (xmlNodePtr)c_property));
2095
+ c_property = c_property->next ;
1679
2096
  }
1680
- }
1681
2097
 
1682
- VALUE cNokogiriXmlNode ;
1683
- VALUE cNokogiriXmlElement ;
2098
+ return rb_properties;
2099
+ }
1684
2100
 
1685
- void init_xml_node()
2101
+ void
2102
+ noko_init_xml_node()
1686
2103
  {
1687
- VALUE nokogiri = rb_define_module("Nokogiri");
1688
- VALUE xml = rb_define_module_under(nokogiri, "XML");
1689
- VALUE klass = rb_define_class_under(xml, "Node", rb_cObject);
1690
-
1691
- cNokogiriXmlNode = klass;
1692
-
1693
- cNokogiriXmlElement = rb_define_class_under(xml, "Element", klass);
1694
-
1695
- rb_define_singleton_method(klass, "new", new, -1);
1696
-
1697
- rb_define_method(klass, "add_namespace_definition", add_namespace_definition, 2);
1698
- rb_define_method(klass, "node_name", get_name, 0);
1699
- rb_define_method(klass, "document", document, 0);
1700
- rb_define_method(klass, "node_name=", set_name, 1);
1701
- rb_define_method(klass, "parent", get_parent, 0);
1702
- rb_define_method(klass, "child", child, 0);
1703
- rb_define_method(klass, "first_element_child", first_element_child, 0);
1704
- rb_define_method(klass, "last_element_child", last_element_child, 0);
1705
- rb_define_method(klass, "children", children, 0);
1706
- rb_define_method(klass, "element_children", element_children, 0);
1707
- rb_define_method(klass, "next_sibling", next_sibling, 0);
1708
- rb_define_method(klass, "previous_sibling", previous_sibling, 0);
1709
- rb_define_method(klass, "next_element", next_element, 0);
1710
- rb_define_method(klass, "previous_element", previous_element, 0);
1711
- rb_define_method(klass, "node_type", node_type, 0);
1712
- rb_define_method(klass, "path", path, 0);
1713
- rb_define_method(klass, "key?", key_eh, 1);
1714
- rb_define_method(klass, "namespaced_key?", namespaced_key_eh, 2);
1715
- rb_define_method(klass, "blank?", blank_eh, 0);
1716
- rb_define_method(klass, "attribute_nodes", attribute_nodes, 0);
1717
- rb_define_method(klass, "attribute", attr, 1);
1718
- rb_define_method(klass, "attribute_with_ns", attribute_with_ns, 2);
1719
- rb_define_method(klass, "namespace", namespace, 0);
1720
- rb_define_method(klass, "namespace_definitions", namespace_definitions, 0);
1721
- rb_define_method(klass, "namespace_scopes", namespace_scopes, 0);
1722
- rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
1723
- rb_define_method(klass, "dup", duplicate_node, -1);
1724
- rb_define_method(klass, "unlink", unlink_node, 0);
1725
- rb_define_method(klass, "internal_subset", internal_subset, 0);
1726
- rb_define_method(klass, "external_subset", external_subset, 0);
1727
- rb_define_method(klass, "create_internal_subset", create_internal_subset, 3);
1728
- rb_define_method(klass, "create_external_subset", create_external_subset, 3);
1729
- rb_define_method(klass, "pointer_id", pointer_id, 0);
1730
- rb_define_method(klass, "line", line, 0);
1731
- rb_define_method(klass, "content", get_native_content, 0);
1732
- rb_define_method(klass, "native_content=", set_native_content, 1);
1733
- rb_define_method(klass, "lang", get_lang, 0);
1734
- rb_define_method(klass, "lang=", set_lang, 1);
1735
-
1736
- rb_define_private_method(klass, "process_xincludes", process_xincludes, 1);
1737
- rb_define_private_method(klass, "in_context", in_context, 2);
1738
- rb_define_private_method(klass, "add_child_node", add_child, 1);
1739
- rb_define_private_method(klass, "add_previous_sibling_node", add_previous_sibling, 1);
1740
- rb_define_private_method(klass, "add_next_sibling_node", add_next_sibling, 1);
1741
- rb_define_private_method(klass, "replace_node", replace, 1);
1742
- rb_define_private_method(klass, "dump_html", dump_html, 0);
1743
- rb_define_private_method(klass, "native_write_to", native_write_to, 4);
1744
- rb_define_private_method(klass, "get", get, 1);
1745
- rb_define_private_method(klass, "set", set, 2);
1746
- rb_define_private_method(klass, "set_namespace", set_namespace, 1);
1747
- rb_define_private_method(klass, "compare", compare, 1);
1748
-
1749
- decorate = rb_intern("decorate");
1750
- decorate_bang = rb_intern("decorate!");
2104
+ cNokogiriXmlNode = rb_define_class_under(mNokogiriXml, "Node", rb_cObject);
2105
+
2106
+ rb_undef_alloc_func(cNokogiriXmlNode);
2107
+
2108
+ rb_define_singleton_method(cNokogiriXmlNode, "new", rb_xml_node_new, -1);
2109
+
2110
+ rb_define_method(cNokogiriXmlNode, "add_namespace_definition", rb_xml_node_add_namespace_definition, 2);
2111
+ rb_define_method(cNokogiriXmlNode, "attribute", rb_xml_node_attribute, 1);
2112
+ rb_define_method(cNokogiriXmlNode, "attribute_nodes", rb_xml_node_attribute_nodes, 0);
2113
+ rb_define_method(cNokogiriXmlNode, "attribute_with_ns", rb_xml_node_attribute_with_ns, 2);
2114
+ rb_define_method(cNokogiriXmlNode, "blank?", rb_xml_node_blank_eh, 0);
2115
+ rb_define_method(cNokogiriXmlNode, "child", rb_xml_node_child, 0);
2116
+ rb_define_method(cNokogiriXmlNode, "children", rb_xml_node_children, 0);
2117
+ rb_define_method(cNokogiriXmlNode, "content", rb_xml_node_content, 0);
2118
+ rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
2119
+ rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
2120
+ rb_define_method(cNokogiriXmlNode, "document", rb_xml_node_document, 0);
2121
+ rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
2122
+ rb_define_method(cNokogiriXmlNode, "element_children", rb_xml_node_element_children, 0);
2123
+ rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
2124
+ rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
2125
+ rb_define_method(cNokogiriXmlNode, "first_element_child", rb_xml_node_first_element_child, 0);
2126
+ rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
2127
+ rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
2128
+ rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
2129
+ rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
2130
+ rb_define_method(cNokogiriXmlNode, "last_element_child", rb_xml_node_last_element_child, 0);
2131
+ rb_define_method(cNokogiriXmlNode, "line", rb_xml_node_line, 0);
2132
+ rb_define_method(cNokogiriXmlNode, "line=", rb_xml_node_line_set, 1);
2133
+ rb_define_method(cNokogiriXmlNode, "namespace", rb_xml_node_namespace, 0);
2134
+ rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
2135
+ rb_define_method(cNokogiriXmlNode, "namespace_scopes", rb_xml_node_namespace_scopes, 0);
2136
+ rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
2137
+ rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
2138
+ rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
2139
+ rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
2140
+ rb_define_method(cNokogiriXmlNode, "node_name", get_name, 0);
2141
+ rb_define_method(cNokogiriXmlNode, "node_name=", set_name, 1);
2142
+ rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
2143
+ rb_define_method(cNokogiriXmlNode, "parent", get_parent, 0);
2144
+ rb_define_method(cNokogiriXmlNode, "path", rb_xml_node_path, 0);
2145
+ rb_define_method(cNokogiriXmlNode, "pointer_id", rb_xml_node_pointer_id, 0);
2146
+ rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
2147
+ rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
2148
+ rb_define_method(cNokogiriXmlNode, "unlink", unlink_node, 0);
2149
+
2150
+ rb_define_private_method(cNokogiriXmlNode, "add_child_node", add_child, 1);
2151
+ rb_define_private_method(cNokogiriXmlNode, "add_next_sibling_node", add_next_sibling, 1);
2152
+ rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
2153
+ rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
2154
+ rb_define_private_method(cNokogiriXmlNode, "dump_html", dump_html, 0);
2155
+ rb_define_private_method(cNokogiriXmlNode, "get", get, 1);
2156
+ rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
2157
+ rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
2158
+ rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
2159
+ rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
2160
+ rb_define_private_method(cNokogiriXmlNode, "set", set, 2);
2161
+ rb_define_private_method(cNokogiriXmlNode, "set_namespace", set_namespace, 1);
2162
+
2163
+ id_decorate = rb_intern("decorate");
2164
+ id_decorate_bang = rb_intern("decorate!");
1751
2165
  }
1752
-
1753
- /* vim: set noet sw=4 sws=4 */