nokogiri 1.11.3 → 1.13.8

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 (179) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/LICENSE-DEPENDENCIES.md +243 -22
  4. data/LICENSE.md +1 -1
  5. data/README.md +14 -11
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +13 -64
  8. data/ext/nokogiri/depend +35 -34
  9. data/ext/nokogiri/extconf.rb +237 -133
  10. data/ext/nokogiri/gumbo.c +584 -0
  11. data/ext/nokogiri/{html_document.c → html4_document.c} +8 -8
  12. data/ext/nokogiri/{html_element_description.c → html4_element_description.c} +21 -19
  13. data/ext/nokogiri/{html_entity_lookup.c → html4_entity_lookup.c} +7 -7
  14. data/ext/nokogiri/{html_sax_parser_context.c → html4_sax_parser_context.c} +8 -8
  15. data/ext/nokogiri/{html_sax_push_parser.c → html4_sax_push_parser.c} +4 -4
  16. data/ext/nokogiri/libxml2_backwards_compat.c +30 -30
  17. data/ext/nokogiri/nokogiri.c +70 -38
  18. data/ext/nokogiri/nokogiri.h +27 -9
  19. data/ext/nokogiri/xml_attr.c +2 -2
  20. data/ext/nokogiri/xml_attribute_decl.c +3 -3
  21. data/ext/nokogiri/xml_cdata.c +1 -1
  22. data/ext/nokogiri/xml_document.c +50 -50
  23. data/ext/nokogiri/xml_document_fragment.c +0 -2
  24. data/ext/nokogiri/xml_dtd.c +10 -10
  25. data/ext/nokogiri/xml_element_content.c +2 -0
  26. data/ext/nokogiri/xml_element_decl.c +3 -3
  27. data/ext/nokogiri/xml_encoding_handler.c +31 -12
  28. data/ext/nokogiri/xml_entity_decl.c +5 -5
  29. data/ext/nokogiri/xml_namespace.c +4 -2
  30. data/ext/nokogiri/xml_node.c +833 -492
  31. data/ext/nokogiri/xml_node_set.c +24 -24
  32. data/ext/nokogiri/xml_reader.c +90 -11
  33. data/ext/nokogiri/xml_sax_parser.c +6 -6
  34. data/ext/nokogiri/xml_sax_parser_context.c +12 -3
  35. data/ext/nokogiri/xml_schema.c +5 -3
  36. data/ext/nokogiri/xml_text.c +1 -1
  37. data/ext/nokogiri/xml_xpath_context.c +110 -85
  38. data/ext/nokogiri/xslt_stylesheet.c +109 -10
  39. data/gumbo-parser/CHANGES.md +63 -0
  40. data/gumbo-parser/Makefile +101 -0
  41. data/gumbo-parser/THANKS +27 -0
  42. data/gumbo-parser/src/Makefile +34 -0
  43. data/gumbo-parser/src/README.md +41 -0
  44. data/gumbo-parser/src/ascii.c +75 -0
  45. data/gumbo-parser/src/ascii.h +115 -0
  46. data/gumbo-parser/src/attribute.c +42 -0
  47. data/gumbo-parser/src/attribute.h +17 -0
  48. data/gumbo-parser/src/char_ref.c +22225 -0
  49. data/gumbo-parser/src/char_ref.h +29 -0
  50. data/gumbo-parser/src/char_ref.rl +2154 -0
  51. data/gumbo-parser/src/error.c +626 -0
  52. data/gumbo-parser/src/error.h +148 -0
  53. data/gumbo-parser/src/foreign_attrs.c +104 -0
  54. data/gumbo-parser/src/foreign_attrs.gperf +27 -0
  55. data/gumbo-parser/src/gumbo.h +943 -0
  56. data/gumbo-parser/src/insertion_mode.h +33 -0
  57. data/gumbo-parser/src/macros.h +91 -0
  58. data/gumbo-parser/src/parser.c +4875 -0
  59. data/gumbo-parser/src/parser.h +41 -0
  60. data/gumbo-parser/src/replacement.h +33 -0
  61. data/gumbo-parser/src/string_buffer.c +103 -0
  62. data/gumbo-parser/src/string_buffer.h +68 -0
  63. data/gumbo-parser/src/string_piece.c +48 -0
  64. data/gumbo-parser/src/svg_attrs.c +174 -0
  65. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  66. data/gumbo-parser/src/svg_tags.c +137 -0
  67. data/gumbo-parser/src/svg_tags.gperf +55 -0
  68. data/gumbo-parser/src/tag.c +222 -0
  69. data/gumbo-parser/src/tag_lookup.c +382 -0
  70. data/gumbo-parser/src/tag_lookup.gperf +169 -0
  71. data/gumbo-parser/src/tag_lookup.h +13 -0
  72. data/gumbo-parser/src/token_buffer.c +79 -0
  73. data/gumbo-parser/src/token_buffer.h +71 -0
  74. data/gumbo-parser/src/token_type.h +17 -0
  75. data/gumbo-parser/src/tokenizer.c +3463 -0
  76. data/gumbo-parser/src/tokenizer.h +112 -0
  77. data/gumbo-parser/src/tokenizer_states.h +339 -0
  78. data/gumbo-parser/src/utf8.c +245 -0
  79. data/gumbo-parser/src/utf8.h +164 -0
  80. data/gumbo-parser/src/util.c +68 -0
  81. data/gumbo-parser/src/util.h +30 -0
  82. data/gumbo-parser/src/vector.c +111 -0
  83. data/gumbo-parser/src/vector.h +45 -0
  84. data/lib/nokogiri/class_resolver.rb +67 -0
  85. data/lib/nokogiri/css/node.rb +9 -8
  86. data/lib/nokogiri/css/parser.rb +361 -342
  87. data/lib/nokogiri/css/parser.y +250 -245
  88. data/lib/nokogiri/css/parser_extras.rb +22 -20
  89. data/lib/nokogiri/css/syntax_error.rb +2 -1
  90. data/lib/nokogiri/css/tokenizer.rb +4 -3
  91. data/lib/nokogiri/css/tokenizer.rex +3 -2
  92. data/lib/nokogiri/css/xpath_visitor.rb +179 -82
  93. data/lib/nokogiri/css.rb +49 -17
  94. data/lib/nokogiri/decorators/slop.rb +8 -7
  95. data/lib/nokogiri/extension.rb +8 -3
  96. data/lib/nokogiri/gumbo.rb +15 -0
  97. data/lib/nokogiri/html.rb +37 -27
  98. data/lib/nokogiri/{html → html4}/builder.rb +3 -2
  99. data/lib/nokogiri/{html → html4}/document.rb +92 -81
  100. data/lib/nokogiri/{html → html4}/document_fragment.rb +13 -9
  101. data/lib/nokogiri/{html → html4}/element_description.rb +2 -1
  102. data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
  103. data/lib/nokogiri/{html → html4}/entity_lookup.rb +3 -2
  104. data/lib/nokogiri/{html → html4}/sax/parser.rb +16 -16
  105. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  106. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +11 -11
  107. data/lib/nokogiri/html4.rb +46 -0
  108. data/lib/nokogiri/html5/document.rb +91 -0
  109. data/lib/nokogiri/html5/document_fragment.rb +83 -0
  110. data/lib/nokogiri/html5/node.rb +100 -0
  111. data/lib/nokogiri/html5.rb +478 -0
  112. data/lib/nokogiri/jruby/dependencies.rb +10 -9
  113. data/lib/nokogiri/syntax_error.rb +1 -0
  114. data/lib/nokogiri/version/constant.rb +2 -1
  115. data/lib/nokogiri/version/info.rb +31 -14
  116. data/lib/nokogiri/version.rb +1 -0
  117. data/lib/nokogiri/xml/attr.rb +5 -3
  118. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  119. data/lib/nokogiri/xml/builder.rb +71 -31
  120. data/lib/nokogiri/xml/cdata.rb +2 -1
  121. data/lib/nokogiri/xml/character_data.rb +1 -0
  122. data/lib/nokogiri/xml/document.rb +183 -96
  123. data/lib/nokogiri/xml/document_fragment.rb +41 -38
  124. data/lib/nokogiri/xml/dtd.rb +3 -2
  125. data/lib/nokogiri/xml/element_content.rb +1 -0
  126. data/lib/nokogiri/xml/element_decl.rb +2 -1
  127. data/lib/nokogiri/xml/entity_decl.rb +3 -2
  128. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  129. data/lib/nokogiri/xml/namespace.rb +2 -0
  130. data/lib/nokogiri/xml/node/save_options.rb +9 -5
  131. data/lib/nokogiri/xml/node.rb +525 -354
  132. data/lib/nokogiri/xml/node_set.rb +50 -54
  133. data/lib/nokogiri/xml/notation.rb +12 -0
  134. data/lib/nokogiri/xml/parse_options.rb +13 -6
  135. data/lib/nokogiri/xml/pp/character_data.rb +8 -6
  136. data/lib/nokogiri/xml/pp/node.rb +24 -26
  137. data/lib/nokogiri/xml/pp.rb +3 -2
  138. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  139. data/lib/nokogiri/xml/reader.rb +20 -24
  140. data/lib/nokogiri/xml/relax_ng.rb +1 -0
  141. data/lib/nokogiri/xml/sax/document.rb +44 -49
  142. data/lib/nokogiri/xml/sax/parser.rb +37 -34
  143. data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
  144. data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
  145. data/lib/nokogiri/xml/sax.rb +5 -4
  146. data/lib/nokogiri/xml/schema.rb +7 -6
  147. data/lib/nokogiri/xml/searchable.rb +93 -62
  148. data/lib/nokogiri/xml/syntax_error.rb +5 -4
  149. data/lib/nokogiri/xml/text.rb +1 -0
  150. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  151. data/lib/nokogiri/xml/xpath.rb +13 -1
  152. data/lib/nokogiri/xml/xpath_context.rb +2 -3
  153. data/lib/nokogiri/xml.rb +37 -37
  154. data/lib/nokogiri/xslt/stylesheet.rb +2 -1
  155. data/lib/nokogiri/xslt.rb +28 -20
  156. data/lib/nokogiri.rb +48 -43
  157. data/lib/xsd/xmlparser/nokogiri.rb +25 -24
  158. data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
  159. data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
  160. data/patches/libxml2/{0004-libxml2.la-is-in-top_builddir.patch → 0003-libxml2.la-is-in-top_builddir.patch} +1 -1
  161. data/patches/libxml2/{0008-use-glibc-strlen.patch → 0004-use-glibc-strlen.patch} +3 -3
  162. data/patches/libxml2/{0009-avoid-isnan-isinf.patch → 0005-avoid-isnan-isinf.patch} +4 -4
  163. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +3040 -0
  164. data/patches/libxml2/0008-htmlParseComment-handle-abruptly-closed-comments.patch +61 -0
  165. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  166. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
  167. data/ports/archives/libxml2-2.9.14.tar.xz +0 -0
  168. data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
  169. metadata +204 -93
  170. data/lib/nokogiri/html/element_description_defaults.rb +0 -672
  171. data/lib/nokogiri/html/sax/parser_context.rb +0 -17
  172. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  173. data/patches/libxml2/0005-Fix-infinite-loop-in-xmlStringLenDecodeEntities.patch +0 -32
  174. data/patches/libxml2/0006-htmlParseComment-treat-as-if-it-closed-the-comment.patch +0 -73
  175. data/patches/libxml2/0007-use-new-htmlParseLookupCommentEnd-to-find-comment-en.patch +0 -103
  176. data/patches/libxml2/0010-parser.c-shrink-the-input-buffer-when-appropriate.patch +0 -70
  177. data/patches/libxml2/0011-update-automake-files-for-arm64.patch +0 -2511
  178. data/ports/archives/libxml2-2.9.10.tar.gz +0 -0
  179. data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
@@ -1,23 +1,30 @@
1
1
  #include <nokogiri.h>
2
2
 
3
- VALUE cNokogiriXmlNode ;
3
+ // :stopdoc:
4
4
 
5
+ VALUE cNokogiriXmlNode ;
5
6
  static ID id_decorate, id_decorate_bang;
6
7
 
8
+ typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
9
+
7
10
  #ifdef DEBUG
8
11
  static void
9
- debug_node_dealloc(xmlNodePtr x)
12
+ _xml_node_dealloc(xmlNodePtr x)
10
13
  {
11
14
  NOKOGIRI_DEBUG_START(x)
12
15
  NOKOGIRI_DEBUG_END(x)
13
16
  }
14
17
  #else
15
- # define debug_node_dealloc 0
18
+ # define _xml_node_dealloc 0
16
19
  #endif
17
20
 
18
21
  static void
19
- mark(xmlNodePtr node)
22
+ _xml_node_mark(xmlNodePtr node)
20
23
  {
24
+ if (!DOC_RUBY_OBJECT_TEST(node->doc)) {
25
+ return;
26
+ }
27
+
21
28
  xmlDocPtr doc = node->doc;
22
29
  if (doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
23
30
  if (DOC_RUBY_OBJECT_TEST(doc)) {
@@ -28,14 +35,37 @@ mark(xmlNodePtr node)
28
35
  }
29
36
  }
30
37
 
31
- /* :nodoc: */
32
- 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
47
+
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
+ };
33
63
 
34
- /* :nodoc: */
35
64
  static void
36
65
  relink_namespace(xmlNodePtr reparented)
37
66
  {
38
67
  xmlNodePtr child;
68
+ xmlAttrPtr attr;
39
69
 
40
70
  if (reparented->type != XML_ATTRIBUTE_NODE &&
41
71
  reparented->type != XML_ELEMENT_NODE) { return; }
@@ -69,7 +99,9 @@ relink_namespace(xmlNodePtr reparented)
69
99
  if (reparented->type != XML_ELEMENT_NODE || !reparented->parent) { return; }
70
100
 
71
101
  /* Make sure that our reparented node has the correct namespaces */
72
- 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)) {
73
105
  xmlSetNs(reparented, reparented->parent->ns);
74
106
  }
75
107
 
@@ -132,15 +164,17 @@ relink_namespace(xmlNodePtr reparented)
132
164
  }
133
165
 
134
166
  if (reparented->type == XML_ELEMENT_NODE) {
135
- child = (xmlNodePtr)((xmlElementPtr)reparented)->attributes;
136
- while (NULL != child) {
137
- relink_namespace(child);
138
- child = child->next;
167
+ attr = reparented->properties;
168
+ while (NULL != attr) {
169
+ relink_namespace((xmlNodePtr)attr);
170
+ attr = attr->next;
139
171
  }
140
172
  }
141
173
  }
142
174
 
143
- /* :nodoc: */
175
+
176
+ /* internal function meant to wrap xmlReplaceNode
177
+ and fix some issues we have with libxml2 merging nodes */
144
178
  static xmlNodePtr
145
179
  xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
146
180
  {
@@ -165,12 +199,23 @@ xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
165
199
  return retval ;
166
200
  }
167
201
 
168
- /* :nodoc: */
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
+
169
214
  static VALUE
170
215
  reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
171
216
  {
172
217
  VALUE reparented_obj ;
173
- xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text, parent ;
218
+ xmlNodePtr reparentee, original_reparentee, pivot, reparented, next_text, new_next_text, parent ;
174
219
  int original_ns_prefix_is_default = 0 ;
175
220
 
176
221
  if (!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
@@ -180,8 +225,8 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
180
225
  rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
181
226
  }
182
227
 
183
- Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
184
- 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);
185
230
 
186
231
  /*
187
232
  * Check if nodes given are appropriate to have a parent-child
@@ -197,66 +242,66 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
197
242
 
198
243
  if (parent) {
199
244
  switch (parent->type) {
200
- case XML_DOCUMENT_NODE:
201
- case XML_HTML_DOCUMENT_NODE:
202
- switch (reparentee->type) {
203
- case XML_ELEMENT_NODE:
204
- case XML_PI_NODE:
205
- case XML_COMMENT_NODE:
206
- case XML_DOCUMENT_TYPE_NODE:
207
- /*
208
- * The DOM specification says no to adding text-like nodes
209
- * directly to a document, but we allow it for compatibility.
210
- */
211
- case XML_TEXT_NODE:
212
- case XML_CDATA_SECTION_NODE:
213
- case XML_ENTITY_REF_NODE:
214
- goto ok;
215
- 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
+ }
216
263
  break;
217
- }
218
- break;
219
- case XML_DOCUMENT_FRAG_NODE:
220
- case XML_ENTITY_REF_NODE:
221
- case XML_ELEMENT_NODE:
222
- switch (reparentee->type) {
223
- case XML_ELEMENT_NODE:
224
- case XML_PI_NODE:
225
- case XML_COMMENT_NODE:
226
- case XML_TEXT_NODE:
227
- case XML_CDATA_SECTION_NODE:
264
+ case XML_DOCUMENT_FRAG_NODE:
228
265
  case XML_ENTITY_REF_NODE:
229
- goto ok;
230
- 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
+ }
231
287
  break;
232
- }
233
- break;
234
- case XML_ATTRIBUTE_NODE:
235
- switch (reparentee->type) {
236
288
  case XML_TEXT_NODE:
237
- case XML_ENTITY_REF_NODE:
238
- 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;
239
296
  default:
240
297
  break;
241
- }
242
- break;
243
- case XML_TEXT_NODE:
244
- /*
245
- * xmlAddChild() breaks the DOM specification in that it allows
246
- * adding a text node to another, in which case text nodes are
247
- * coalesced, but since our JRuby version does not support such
248
- * operation, we should inhibit it.
249
- */
250
- break;
251
- default:
252
- break;
253
298
  }
254
299
 
255
300
  rb_raise(rb_eArgError, "cannot reparent %s there", rb_obj_classname(reparentee_obj));
256
301
  }
257
302
 
258
303
  ok:
259
- xmlUnlinkNode(reparentee);
304
+ original_reparentee = reparentee;
260
305
 
261
306
  if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
262
307
  /*
@@ -308,11 +353,13 @@ ok:
308
353
  * issue #391, where new node's prefix may become the string "default"
309
354
  * see libxml2 tree.c xmlNewReconciliedNs which implements this behavior.
310
355
  */
311
- xmlFree((xmlChar *)reparentee->ns->prefix);
356
+ xmlFree(DISCARD_CONST_QUAL_XMLCHAR(reparentee->ns->prefix));
312
357
  reparentee->ns->prefix = NULL;
313
358
  }
314
359
  }
315
360
 
361
+ xmlUnlinkNode(original_reparentee);
362
+
316
363
  if (prf != xmlAddPrevSibling && prf != xmlAddNextSibling
317
364
  && reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
318
365
  /*
@@ -352,49 +399,421 @@ ok:
352
399
  * adjacent text nodes.
353
400
  */
354
401
  DATA_PTR(reparentee_obj) = reparented ;
355
-
356
- relink_namespace(reparented);
357
-
358
402
  reparented_obj = noko_xml_node_wrap(Qnil, reparented);
359
403
 
360
404
  rb_funcall(reparented_obj, id_decorate_bang, 0);
361
405
 
406
+ /* if we've created a cycle, raise an exception */
407
+ raise_if_ancestor_of_self(reparented);
408
+
409
+ relink_namespace(reparented);
410
+
362
411
  return reparented_obj ;
363
412
  }
364
413
 
414
+ // :startdoc:
365
415
 
366
416
  /*
367
- * call-seq:
368
- * 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"
369
460
  *
370
- * Get the document for this Node
371
461
  */
372
462
  static VALUE
373
- document(VALUE self)
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)
374
533
  {
375
534
  xmlNodePtr node;
376
- Data_Get_Struct(self, xmlNode, 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.
746
+ *
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"
765
+ */
766
+ static VALUE
767
+ rb_xml_node_content(VALUE self)
768
+ {
769
+ xmlNodePtr 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);
377
796
  return DOC_RUBY_OBJECT(node->doc);
378
797
  }
379
798
 
380
799
  /*
381
- * call-seq:
382
- * pointer_id
800
+ * :call-seq: pointer_id() → Integer
383
801
  *
384
- * 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.
385
805
  */
386
806
  static VALUE
387
- pointer_id(VALUE self)
807
+ rb_xml_node_pointer_id(VALUE self)
388
808
  {
389
809
  xmlNodePtr node;
390
- Data_Get_Struct(self, xmlNode, node);
810
+ Noko_Node_Get_Struct(self, xmlNode, node);
391
811
 
392
812
  return INT2NUM((long)(node));
393
813
  }
394
814
 
395
815
  /*
396
- * call-seq:
397
- * encode_special_chars(string)
816
+ * :call-seq: encode_special_chars(string) → String
398
817
  *
399
818
  * Encode any special characters in +string+
400
819
  */
@@ -405,7 +824,7 @@ encode_special_chars(VALUE self, VALUE string)
405
824
  xmlChar *encoded;
406
825
  VALUE encoded_str;
407
826
 
408
- Data_Get_Struct(self, xmlNode, node);
827
+ Noko_Node_Get_Struct(self, xmlNode, node);
409
828
  encoded = xmlEncodeSpecialChars(
410
829
  node->doc,
411
830
  (const xmlChar *)StringValueCStr(string)
@@ -418,8 +837,8 @@ encode_special_chars(VALUE self, VALUE string)
418
837
  }
419
838
 
420
839
  /*
421
- * call-seq:
422
- * create_internal_subset(name, external_id, system_id)
840
+ * :call-seq:
841
+ * create_internal_subset(name, external_id, system_id)
423
842
  *
424
843
  * Create the internal subset of a document.
425
844
  *
@@ -436,7 +855,7 @@ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
436
855
  xmlDocPtr doc;
437
856
  xmlDtdPtr dtd;
438
857
 
439
- Data_Get_Struct(self, xmlNode, node);
858
+ Noko_Node_Get_Struct(self, xmlNode, node);
440
859
 
441
860
  doc = node->doc;
442
861
 
@@ -457,8 +876,8 @@ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
457
876
  }
458
877
 
459
878
  /*
460
- * call-seq:
461
- * create_external_subset(name, external_id, system_id)
879
+ * :call-seq:
880
+ * create_external_subset(name, external_id, system_id)
462
881
  *
463
882
  * Create an external subset
464
883
  */
@@ -469,7 +888,7 @@ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
469
888
  xmlDocPtr doc;
470
889
  xmlDtdPtr dtd;
471
890
 
472
- Data_Get_Struct(self, xmlNode, node);
891
+ Noko_Node_Get_Struct(self, xmlNode, node);
473
892
 
474
893
  doc = node->doc;
475
894
 
@@ -490,8 +909,8 @@ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
490
909
  }
491
910
 
492
911
  /*
493
- * call-seq:
494
- * external_subset
912
+ * :call-seq:
913
+ * external_subset()
495
914
  *
496
915
  * Get the external subset
497
916
  */
@@ -502,7 +921,7 @@ external_subset(VALUE self)
502
921
  xmlDocPtr doc;
503
922
  xmlDtdPtr dtd;
504
923
 
505
- Data_Get_Struct(self, xmlNode, node);
924
+ Noko_Node_Get_Struct(self, xmlNode, node);
506
925
 
507
926
  if (!node->doc) { return Qnil; }
508
927
 
@@ -515,8 +934,8 @@ external_subset(VALUE self)
515
934
  }
516
935
 
517
936
  /*
518
- * call-seq:
519
- * internal_subset
937
+ * :call-seq:
938
+ * internal_subset()
520
939
  *
521
940
  * Get the internal subset
522
941
  */
@@ -527,7 +946,7 @@ internal_subset(VALUE self)
527
946
  xmlDocPtr doc;
528
947
  xmlDtdPtr dtd;
529
948
 
530
- Data_Get_Struct(self, xmlNode, node);
949
+ Noko_Node_Get_Struct(self, xmlNode, node);
531
950
 
532
951
  if (!node->doc) { return Qnil; }
533
952
 
@@ -540,16 +959,19 @@ internal_subset(VALUE self)
540
959
  }
541
960
 
542
961
  /*
543
- * call-seq:
544
- * dup
545
- * dup(depth)
546
- * 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
547
966
  *
548
967
  * Copy this node.
549
- * An optional depth may be passed in. 0 is a shallow copy, 1 (the default) is a deep copy.
550
- * An optional new_parent_doc may also be passed in, which will be the new
551
- * node's parent document. Defaults to the current node's document.
552
- * 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
553
975
  */
554
976
  static VALUE
555
977
  duplicate_node(int argc, VALUE *argv, VALUE self)
@@ -560,7 +982,7 @@ duplicate_node(int argc, VALUE *argv, VALUE self)
560
982
  xmlDocPtr new_parent_doc;
561
983
  xmlNodePtr node, dup;
562
984
 
563
- Data_Get_Struct(self, xmlNode, node);
985
+ Noko_Node_Get_Struct(self, xmlNode, node);
564
986
 
565
987
  n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
566
988
 
@@ -584,35 +1006,22 @@ duplicate_node(int argc, VALUE *argv, VALUE self)
584
1006
  }
585
1007
 
586
1008
  /*
587
- * call-seq:
588
- * unlink
589
- *
590
- * Unlink this node from its current context.
591
- */
592
- static VALUE
593
- unlink_node(VALUE self)
594
- {
595
- xmlNodePtr node;
596
- Data_Get_Struct(self, xmlNode, node);
597
- xmlUnlinkNode(node);
598
- noko_xml_document_pin_node(node);
599
- return self;
600
- }
601
-
602
- /*
603
- * call-seq:
604
- * blank?
1009
+ * :call-seq:
1010
+ * unlink() → self
605
1011
  *
606
- * Is this node blank?
1012
+ * Unlink this node from its current context.
607
1013
  */
608
1014
  static VALUE
609
- blank_eh(VALUE self)
1015
+ unlink_node(VALUE self)
610
1016
  {
611
1017
  xmlNodePtr node;
612
- Data_Get_Struct(self, xmlNode, node);
613
- return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
1018
+ Noko_Node_Get_Struct(self, xmlNode, node);
1019
+ xmlUnlinkNode(node);
1020
+ noko_xml_document_pin_node(node);
1021
+ return self;
614
1022
  }
615
1023
 
1024
+
616
1025
  /*
617
1026
  * call-seq:
618
1027
  * next_sibling
@@ -623,7 +1032,7 @@ static VALUE
623
1032
  next_sibling(VALUE self)
624
1033
  {
625
1034
  xmlNodePtr node, sibling;
626
- Data_Get_Struct(self, xmlNode, node);
1035
+ Noko_Node_Get_Struct(self, xmlNode, node);
627
1036
 
628
1037
  sibling = node->next;
629
1038
  if (!sibling) { return Qnil; }
@@ -641,7 +1050,7 @@ static VALUE
641
1050
  previous_sibling(VALUE self)
642
1051
  {
643
1052
  xmlNodePtr node, sibling;
644
- Data_Get_Struct(self, xmlNode, node);
1053
+ Noko_Node_Get_Struct(self, xmlNode, node);
645
1054
 
646
1055
  sibling = node->prev;
647
1056
  if (!sibling) { return Qnil; }
@@ -659,7 +1068,7 @@ static VALUE
659
1068
  next_element(VALUE self)
660
1069
  {
661
1070
  xmlNodePtr node, sibling;
662
- Data_Get_Struct(self, xmlNode, node);
1071
+ Noko_Node_Get_Struct(self, xmlNode, node);
663
1072
 
664
1073
  sibling = xmlNextElementSibling(node);
665
1074
  if (!sibling) { return Qnil; }
@@ -677,7 +1086,7 @@ static VALUE
677
1086
  previous_element(VALUE self)
678
1087
  {
679
1088
  xmlNodePtr node, sibling;
680
- Data_Get_Struct(self, xmlNode, node);
1089
+ Noko_Node_Get_Struct(self, xmlNode, node);
681
1090
 
682
1091
  /*
683
1092
  * note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
@@ -699,60 +1108,34 @@ replace(VALUE self, VALUE new_node)
699
1108
  VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
700
1109
 
701
1110
  xmlNodePtr pivot;
702
- Data_Get_Struct(self, xmlNode, pivot);
1111
+ Noko_Node_Get_Struct(self, xmlNode, pivot);
703
1112
  noko_xml_document_pin_node(pivot);
704
1113
 
705
1114
  return reparent;
706
1115
  }
707
1116
 
708
1117
  /*
709
- * call-seq:
710
- * children
1118
+ * :call-seq:
1119
+ * element_children() → NodeSet
1120
+ * elements() → NodeSet
711
1121
  *
712
- * Get the list of children for this node as a NodeSet
713
- */
714
- static VALUE
715
- children(VALUE self)
716
- {
717
- xmlNodePtr node;
718
- xmlNodePtr child;
719
- xmlNodeSetPtr set;
720
- VALUE document;
721
- VALUE node_set;
722
-
723
- Data_Get_Struct(self, xmlNode, node);
724
-
725
- child = node->children;
726
- set = xmlXPathNodeSetCreate(child);
727
-
728
- document = DOC_RUBY_OBJECT(node->doc);
729
-
730
- if (!child) { return noko_xml_node_set_wrap(set, document); }
731
-
732
- child = child->next;
733
- while (NULL != child) {
734
- xmlXPathNodeSetAddUnique(set, child);
735
- child = child->next;
736
- }
737
-
738
- node_set = noko_xml_node_set_wrap(set, document);
739
-
740
- return node_set;
741
- }
742
-
743
- /*
744
- * call-seq:
745
- * 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.
746
1125
  *
747
- * Get the list of children for this node as a NodeSet. All nodes will be
748
- * element nodes.
1126
+ * *Example:*
749
1127
  *
750
- * Example:
1128
+ * Note that #children returns the Text node "hello" while #element_children does not.
751
1129
  *
752
- * @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">]>]
753
1136
  */
754
1137
  static VALUE
755
- element_children(VALUE self)
1138
+ rb_xml_node_element_children(VALUE self)
756
1139
  {
757
1140
  xmlNodePtr node;
758
1141
  xmlNodePtr child;
@@ -760,7 +1143,7 @@ element_children(VALUE self)
760
1143
  VALUE document;
761
1144
  VALUE node_set;
762
1145
 
763
- Data_Get_Struct(self, xmlNode, node);
1146
+ Noko_Node_Get_Struct(self, xmlNode, node);
764
1147
 
765
1148
  child = xmlFirstElementChild(node);
766
1149
  set = xmlXPathNodeSetCreate(child);
@@ -781,38 +1164,25 @@ element_children(VALUE self)
781
1164
  }
782
1165
 
783
1166
  /*
784
- * call-seq:
785
- * child
1167
+ * :call-seq:
1168
+ * first_element_child() → Node
786
1169
  *
787
- * Returns the child node
788
- */
789
- static VALUE
790
- child(VALUE self)
791
- {
792
- xmlNodePtr node, child;
793
- Data_Get_Struct(self, xmlNode, node);
794
-
795
- child = node->children;
796
- if (!child) { return Qnil; }
797
-
798
- return noko_xml_node_wrap(Qnil, child);
799
- }
800
-
801
- /*
802
- * call-seq:
803
- * first_element_child
1170
+ * [Returns] The first child Node that is an element.
804
1171
  *
805
- * Returns the first child node of this node that is an element.
1172
+ * *Example:*
806
1173
  *
807
- * Example:
1174
+ * Note that the "hello" child, which is a Text node, is skipped and the <tt><span></tt> element is
1175
+ * returned.
808
1176
  *
809
- * @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")] })
810
1180
  */
811
1181
  static VALUE
812
- first_element_child(VALUE self)
1182
+ rb_xml_node_first_element_child(VALUE self)
813
1183
  {
814
1184
  xmlNodePtr node, child;
815
- Data_Get_Struct(self, xmlNode, node);
1185
+ Noko_Node_Get_Struct(self, xmlNode, node);
816
1186
 
817
1187
  child = xmlFirstElementChild(node);
818
1188
  if (!child) { return Qnil; }
@@ -821,20 +1191,25 @@ first_element_child(VALUE self)
821
1191
  }
822
1192
 
823
1193
  /*
824
- * call-seq:
825
- * last_element_child
1194
+ * :call-seq:
1195
+ * last_element_child() → Node
826
1196
  *
827
- * Returns the last child node of this node that is an element.
1197
+ * [Returns] The last child Node that is an element.
828
1198
  *
829
- * Example:
1199
+ * *Example:*
830
1200
  *
831
- * @doc.root.last_element_child.element? # => true
1201
+ * Note that the "hello" child, which is a Text node, is skipped and the <tt><span>yes</span></tt>
1202
+ * element is returned.
1203
+ *
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")] })
832
1207
  */
833
1208
  static VALUE
834
- last_element_child(VALUE self)
1209
+ rb_xml_node_last_element_child(VALUE self)
835
1210
  {
836
1211
  xmlNodePtr node, child;
837
- Data_Get_Struct(self, xmlNode, node);
1212
+ Noko_Node_Get_Struct(self, xmlNode, node);
838
1213
 
839
1214
  child = xmlLastElementChild(node);
840
1215
  if (!child) { return Qnil; }
@@ -852,7 +1227,7 @@ static VALUE
852
1227
  key_eh(VALUE self, VALUE attribute)
853
1228
  {
854
1229
  xmlNodePtr node;
855
- Data_Get_Struct(self, xmlNode, node);
1230
+ Noko_Node_Get_Struct(self, xmlNode, node);
856
1231
  if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
857
1232
  return Qtrue;
858
1233
  }
@@ -869,7 +1244,7 @@ static VALUE
869
1244
  namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
870
1245
  {
871
1246
  xmlNodePtr node;
872
- Data_Get_Struct(self, xmlNode, node);
1247
+ Noko_Node_Get_Struct(self, xmlNode, node);
873
1248
  if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
874
1249
  NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
875
1250
  return Qtrue;
@@ -888,7 +1263,7 @@ set(VALUE self, VALUE property, VALUE value)
888
1263
  {
889
1264
  xmlNodePtr node, cur;
890
1265
  xmlAttrPtr prop;
891
- Data_Get_Struct(self, xmlNode, node);
1266
+ Noko_Node_Get_Struct(self, xmlNode, node);
892
1267
 
893
1268
  /* If a matching attribute node already exists, then xmlSetProp will destroy
894
1269
  * the existing node's children. However, if Nokogiri has a node object
@@ -933,10 +1308,10 @@ get(VALUE self, VALUE rattribute)
933
1308
 
934
1309
  if (NIL_P(rattribute)) { return Qnil; }
935
1310
 
936
- Data_Get_Struct(self, xmlNode, node);
1311
+ Noko_Node_Get_Struct(self, xmlNode, node);
937
1312
  attribute = xmlCharStrdup(StringValueCStr(rattribute));
938
1313
 
939
- colon = (xmlChar *)(uintptr_t)xmlStrchr(attribute, (const xmlChar)':');
1314
+ colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
940
1315
  if (colon) {
941
1316
  /* split the attribute string into separate prefix and name by
942
1317
  * null-terminating the prefix at the colon */
@@ -975,7 +1350,7 @@ set_namespace(VALUE self, VALUE namespace)
975
1350
  xmlNodePtr node;
976
1351
  xmlNsPtr ns = NULL;
977
1352
 
978
- Data_Get_Struct(self, xmlNode, node);
1353
+ Noko_Node_Get_Struct(self, xmlNode, node);
979
1354
 
980
1355
  if (!NIL_P(namespace)) {
981
1356
  Data_Get_Struct(namespace, xmlNs, ns);
@@ -987,70 +1362,32 @@ set_namespace(VALUE self, VALUE namespace)
987
1362
  }
988
1363
 
989
1364
  /*
990
- * call-seq:
991
- * attribute(name)
1365
+ * :call-seq:
1366
+ * namespace() → Namespace
992
1367
  *
993
- * Get the attribute node with +name+
994
- */
995
- static VALUE
996
- attr(VALUE self, VALUE name)
997
- {
998
- xmlNodePtr node;
999
- xmlAttrPtr prop;
1000
- Data_Get_Struct(self, xmlNode, node);
1001
- prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
1002
-
1003
- if (! prop) { return Qnil; }
1004
- return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
1005
- }
1006
-
1007
- /*
1008
- * call-seq:
1009
- * attribute_with_ns(name, namespace)
1368
+ * [Returns] The Namespace of the element or attribute node, or +nil+ if there is no namespace.
1010
1369
  *
1011
- * Get the attribute node with +name+ and +namespace+
1012
- */
1013
- static VALUE
1014
- attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
1015
- {
1016
- xmlNodePtr node;
1017
- xmlAttrPtr prop;
1018
- Data_Get_Struct(self, xmlNode, node);
1019
- prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
1020
- NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
1021
-
1022
- if (! prop) { return Qnil; }
1023
- return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
1024
- }
1025
-
1026
- /*
1027
- * @overload attribute_nodes()
1028
- * Get the attributes for a Node
1029
- * @return [Array<Nokogiri::XML::Attr>] containing the Node's attributes.
1030
- */
1031
- static VALUE
1032
- attribute_nodes(VALUE rb_node)
1033
- {
1034
- xmlNodePtr c_node;
1035
-
1036
- Data_Get_Struct(rb_node, xmlNode, c_node);
1037
-
1038
- return noko_xml_node_attrs(c_node);
1039
- }
1040
-
1041
-
1042
- /*
1043
- * call-seq:
1044
- * namespace()
1370
+ * *Example:*
1045
1371
  *
1046
- * returns the namespace of the element or attribute node as a Namespace
1047
- * object, or nil if there is no namespace for the element or attribute.
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" })
1048
1385
  */
1049
1386
  static VALUE
1050
- noko_xml_node_namespace(VALUE rb_node)
1387
+ rb_xml_node_namespace(VALUE rb_node)
1051
1388
  {
1052
1389
  xmlNodePtr c_node ;
1053
- Data_Get_Struct(rb_node, xmlNode, c_node);
1390
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1054
1391
 
1055
1392
  if (c_node->ns) {
1056
1393
  return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
@@ -1060,10 +1397,32 @@ noko_xml_node_namespace(VALUE rb_node)
1060
1397
  }
1061
1398
 
1062
1399
  /*
1063
- * call-seq:
1064
- * namespace_definitions()
1400
+ * :call-seq:
1401
+ * namespace_definitions() → Array<Nokogiri::XML::Namespace>
1402
+ *
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.
1065
1406
  *
1066
- * 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" })]
1067
1426
  */
1068
1427
  static VALUE
1069
1428
  namespace_definitions(VALUE rb_node)
@@ -1073,7 +1432,7 @@ namespace_definitions(VALUE rb_node)
1073
1432
  xmlNsPtr c_namespace;
1074
1433
  VALUE definitions = rb_ary_new();
1075
1434
 
1076
- Data_Get_Struct(rb_node, xmlNode, c_node);
1435
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1077
1436
 
1078
1437
  c_namespace = c_node->nsDef;
1079
1438
  if (!c_namespace) {
@@ -1089,23 +1448,42 @@ namespace_definitions(VALUE rb_node)
1089
1448
  }
1090
1449
 
1091
1450
  /*
1092
- * call-seq:
1093
- * 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.
1094
1455
  *
1095
- * returns namespaces in scope for self -- those defined on self element
1096
- * directly or any ancestor node -- as an array of Namespace objects. Default
1097
- * namespaces ("xmlns=" style) for self are included in this array; Default
1098
- * 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" })]
1099
1477
  */
1100
1478
  static VALUE
1101
- namespace_scopes(VALUE rb_node)
1479
+ rb_xml_node_namespace_scopes(VALUE rb_node)
1102
1480
  {
1103
1481
  xmlNodePtr c_node ;
1104
1482
  xmlNsPtr *namespaces;
1105
1483
  VALUE scopes = rb_ary_new();
1106
1484
  int j;
1107
1485
 
1108
- Data_Get_Struct(rb_node, xmlNode, c_node);
1486
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1109
1487
 
1110
1488
  namespaces = xmlGetNsList(c_node->doc, c_node);
1111
1489
  if (!namespaces) {
@@ -1130,7 +1508,7 @@ static VALUE
1130
1508
  node_type(VALUE self)
1131
1509
  {
1132
1510
  xmlNodePtr node;
1133
- Data_Get_Struct(self, xmlNode, node);
1511
+ Noko_Node_Get_Struct(self, xmlNode, node);
1134
1512
  return INT2NUM((long)node->type);
1135
1513
  }
1136
1514
 
@@ -1144,7 +1522,7 @@ static VALUE
1144
1522
  set_native_content(VALUE self, VALUE content)
1145
1523
  {
1146
1524
  xmlNodePtr node, child, next ;
1147
- Data_Get_Struct(self, xmlNode, node);
1525
+ Noko_Node_Get_Struct(self, xmlNode, node);
1148
1526
 
1149
1527
  child = node->children;
1150
1528
  while (NULL != child) {
@@ -1158,30 +1536,6 @@ set_native_content(VALUE self, VALUE content)
1158
1536
  return content;
1159
1537
  }
1160
1538
 
1161
- /*
1162
- * call-seq:
1163
- * content
1164
- *
1165
- * Returns the plaintext content for this Node. Note that entities will always
1166
- * be expanded in the returned string.
1167
- */
1168
- static VALUE
1169
- get_native_content(VALUE self)
1170
- {
1171
- xmlNodePtr node;
1172
- xmlChar *content;
1173
-
1174
- Data_Get_Struct(self, xmlNode, node);
1175
-
1176
- content = xmlNodeGetContent(node);
1177
- if (content) {
1178
- VALUE rval = NOKOGIRI_STR_NEW2(content);
1179
- xmlFree(content);
1180
- return rval;
1181
- }
1182
- return Qnil;
1183
- }
1184
-
1185
1539
  /*
1186
1540
  * call-seq:
1187
1541
  * lang=
@@ -1194,7 +1548,7 @@ set_lang(VALUE self_rb, VALUE lang_rb)
1194
1548
  xmlNodePtr self ;
1195
1549
  xmlChar *lang ;
1196
1550
 
1197
- Data_Get_Struct(self_rb, xmlNode, self);
1551
+ Noko_Node_Get_Struct(self_rb, xmlNode, self);
1198
1552
  lang = (xmlChar *)StringValueCStr(lang_rb);
1199
1553
 
1200
1554
  xmlNodeSetLang(self, lang);
@@ -1216,7 +1570,7 @@ get_lang(VALUE self_rb)
1216
1570
  xmlChar *lang ;
1217
1571
  VALUE lang_rb ;
1218
1572
 
1219
- Data_Get_Struct(self_rb, xmlNode, self);
1573
+ Noko_Node_Get_Struct(self_rb, xmlNode, self);
1220
1574
 
1221
1575
  lang = xmlNodeGetLang(self);
1222
1576
  if (lang) {
@@ -1245,7 +1599,7 @@ static VALUE
1245
1599
  get_parent(VALUE self)
1246
1600
  {
1247
1601
  xmlNodePtr node, parent;
1248
- Data_Get_Struct(self, xmlNode, node);
1602
+ Noko_Node_Get_Struct(self, xmlNode, node);
1249
1603
 
1250
1604
  parent = node->parent;
1251
1605
  if (!parent) { return Qnil; }
@@ -1263,7 +1617,7 @@ static VALUE
1263
1617
  set_name(VALUE self, VALUE new_name)
1264
1618
  {
1265
1619
  xmlNodePtr node;
1266
- Data_Get_Struct(self, xmlNode, node);
1620
+ Noko_Node_Get_Struct(self, xmlNode, node);
1267
1621
  xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
1268
1622
  return new_name;
1269
1623
  }
@@ -1278,7 +1632,7 @@ static VALUE
1278
1632
  get_name(VALUE self)
1279
1633
  {
1280
1634
  xmlNodePtr node;
1281
- Data_Get_Struct(self, xmlNode, node);
1635
+ Noko_Node_Get_Struct(self, xmlNode, node);
1282
1636
  if (node->name) {
1283
1637
  return NOKOGIRI_STR_NEW2(node->name);
1284
1638
  }
@@ -1292,17 +1646,25 @@ get_name(VALUE self)
1292
1646
  * Returns the path associated with this Node
1293
1647
  */
1294
1648
  static VALUE
1295
- path(VALUE self)
1649
+ rb_xml_node_path(VALUE rb_node)
1296
1650
  {
1297
- xmlNodePtr node;
1298
- xmlChar *path ;
1651
+ xmlNodePtr c_node;
1652
+ xmlChar *c_path ;
1299
1653
  VALUE rval;
1300
1654
 
1301
- 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
+ }
1302
1667
 
1303
- path = xmlGetNodePath(node);
1304
- rval = NOKOGIRI_STR_NEW2(path);
1305
- xmlFree(path);
1306
1668
  return rval ;
1307
1669
  }
1308
1670
 
@@ -1339,7 +1701,7 @@ native_write_to(
1339
1701
  const char *before_indent;
1340
1702
  xmlSaveCtxtPtr savectx;
1341
1703
 
1342
- Data_Get_Struct(self, xmlNode, node);
1704
+ Noko_Node_Get_Struct(self, xmlNode, node);
1343
1705
 
1344
1706
  xmlIndentTreeOutput = 1;
1345
1707
 
@@ -1363,18 +1725,39 @@ native_write_to(
1363
1725
  }
1364
1726
 
1365
1727
  /*
1366
- * call-seq:
1367
- * line
1728
+ * :call-seq:
1729
+ * line() → Integer
1730
+ *
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)
1368
1747
  *
1369
- * Returns the line for this Node
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
1370
1753
  */
1371
1754
  static VALUE
1372
- line(VALUE self)
1755
+ rb_xml_node_line(VALUE rb_node)
1373
1756
  {
1374
- xmlNodePtr node;
1375
- Data_Get_Struct(self, xmlNode, node);
1757
+ xmlNodePtr c_node;
1758
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1376
1759
 
1377
- return INT2NUM(xmlGetLineNo(node));
1760
+ return INT2NUM(xmlGetLineNo(c_node));
1378
1761
  }
1379
1762
 
1380
1763
  /*
@@ -1384,90 +1767,56 @@ line(VALUE self)
1384
1767
  * Sets the line for this Node. num must be less than 65535.
1385
1768
  */
1386
1769
  static VALUE
1387
- set_line(VALUE self, VALUE num)
1388
- {
1389
- xmlNodePtr node;
1390
- int value = NUM2INT(num);
1391
-
1392
- Data_Get_Struct(self, xmlNode, node);
1393
- if (value < 65535) {
1394
- node->line = value;
1395
- }
1396
-
1397
- return num;
1398
- }
1399
-
1400
- /*
1401
- * call-seq:
1402
- * add_namespace_definition(prefix, href)
1403
- *
1404
- * Adds a namespace definition with +prefix+ using +href+ value. The result is
1405
- * as if parsed XML for this node had included an attribute
1406
- * 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
1407
- * added by passing 'nil' for prefix. Namespaces added this way will not
1408
- * show up in #attributes, but they will be included as an xmlns attribute
1409
- * when the node is serialized to XML.
1410
- */
1411
- static VALUE
1412
- add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
1770
+ rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
1413
1771
  {
1414
- xmlNodePtr c_node, element;
1415
- xmlNsPtr c_namespace;
1416
- const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
1417
-
1418
- Data_Get_Struct(rb_node, xmlNode, c_node);
1419
- element = c_node ;
1772
+ xmlNodePtr c_node;
1773
+ int line_number = NUM2INT(rb_line_number);
1420
1774
 
1421
- c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
1775
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1422
1776
 
1423
- if (!c_namespace) {
1424
- if (c_node->type != XML_ELEMENT_NODE) {
1425
- element = c_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;
1426
1785
  }
1427
- c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
1428
- }
1429
-
1430
- if (!c_namespace) {
1431
- return Qnil ;
1432
- }
1433
-
1434
- if (NIL_P(rb_prefix) || c_node != element) {
1435
- xmlSetNs(c_node, c_namespace);
1436
1786
  }
1437
1787
 
1438
- return noko_xml_namespace_wrap(c_namespace, c_node->doc);
1788
+ return rb_line_number;
1439
1789
  }
1440
1790
 
1441
- /*
1442
- * @overload new(name, document)
1443
- * Create a new node with +name+ sharing GC lifecycle with +document+.
1444
- * @param name [String]
1445
- * @param document [Nokogiri::XML::Document]
1446
- * @yieldparam node [Nokogiri::XML::Node]
1447
- * @return [Nokogiri::XML::Node]
1448
- * @see Nokogiri::XML::Node#initialize
1449
- */
1791
+ /* :nodoc: documented in lib/nokogiri/xml/node.rb */
1450
1792
  static VALUE
1451
1793
  rb_xml_node_new(int argc, VALUE *argv, VALUE klass)
1452
1794
  {
1453
- xmlDocPtr doc;
1454
- xmlNodePtr node;
1455
- VALUE name;
1456
- VALUE document;
1795
+ xmlNodePtr c_document_node;
1796
+ xmlNodePtr c_node;
1797
+ VALUE rb_name;
1798
+ VALUE rb_document_node;
1457
1799
  VALUE rest;
1458
1800
  VALUE rb_node;
1459
1801
 
1460
- rb_scan_args(argc, argv, "2*", &name, &document, &rest);
1802
+ rb_scan_args(argc, argv, "2*", &rb_name, &rb_document_node, &rest);
1461
1803
 
1462
- 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);
1463
1812
 
1464
- node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(name));
1465
- node->doc = doc->doc;
1466
- noko_xml_document_pin_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);
1467
1816
 
1468
1817
  rb_node = noko_xml_node_wrap(
1469
1818
  klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1470
- node
1819
+ c_node
1471
1820
  );
1472
1821
  rb_obj_call_init(rb_node, argc, argv);
1473
1822
 
@@ -1489,7 +1838,7 @@ dump_html(VALUE self)
1489
1838
  xmlNodePtr node ;
1490
1839
  VALUE html;
1491
1840
 
1492
- Data_Get_Struct(self, xmlNode, node);
1841
+ Noko_Node_Get_Struct(self, xmlNode, node);
1493
1842
 
1494
1843
  buf = xmlBufferCreate() ;
1495
1844
  htmlNodeDump(buf, node->doc, node);
@@ -1508,8 +1857,8 @@ static VALUE
1508
1857
  compare(VALUE self, VALUE _other)
1509
1858
  {
1510
1859
  xmlNodePtr node, other;
1511
- Data_Get_Struct(self, xmlNode, node);
1512
- Data_Get_Struct(_other, xmlNode, other);
1860
+ Noko_Node_Get_Struct(self, xmlNode, node);
1861
+ Noko_Node_Get_Struct(_other, xmlNode, other);
1513
1862
 
1514
1863
  return INT2NUM((long)xmlXPathCmpNodes(other, node));
1515
1864
  }
@@ -1529,7 +1878,7 @@ process_xincludes(VALUE self, VALUE options)
1529
1878
  xmlNodePtr node;
1530
1879
  VALUE error_list = rb_ary_new();
1531
1880
 
1532
- Data_Get_Struct(self, xmlNode, node);
1881
+ Noko_Node_Get_Struct(self, xmlNode, node);
1533
1882
 
1534
1883
  xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
1535
1884
  rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
@@ -1560,7 +1909,7 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1560
1909
  VALUE doc, err;
1561
1910
  int doc_is_empty;
1562
1911
 
1563
- Data_Get_Struct(self, xmlNode, node);
1912
+ Noko_Node_Get_Struct(self, xmlNode, node);
1564
1913
 
1565
1914
  doc = DOC_RUBY_OBJECT(node->doc);
1566
1915
  err = rb_iv_get(doc, "@errors");
@@ -1601,9 +1950,7 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1601
1950
  */
1602
1951
  child_iter = node->doc->children ;
1603
1952
  while (child_iter) {
1604
- if (child_iter->parent != (xmlNodePtr)node->doc) {
1605
- child_iter->parent = (xmlNodePtr)node->doc;
1606
- }
1953
+ child_iter->parent = (xmlNodePtr)node->doc;
1607
1954
  child_iter = child_iter->next;
1608
1955
  }
1609
1956
 
@@ -1633,12 +1980,12 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1633
1980
 
1634
1981
  /* FIXME: This probably needs to handle more constants... */
1635
1982
  switch (error) {
1636
- case XML_ERR_INTERNAL_ERROR:
1637
- case XML_ERR_NO_MEMORY:
1638
- rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
1639
- break;
1640
- default:
1641
- 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;
1642
1989
  }
1643
1990
 
1644
1991
  set = xmlXPathNodeSetCreate(NULL);
@@ -1654,14 +2001,12 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1654
2001
  return noko_xml_node_set_wrap(set, doc);
1655
2002
  }
1656
2003
 
1657
-
1658
2004
  VALUE
1659
2005
  noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1660
2006
  {
1661
2007
  VALUE rb_document, rb_node_cache, rb_node;
1662
2008
  nokogiriTuplePtr node_has_a_document;
1663
2009
  xmlDocPtr c_doc;
1664
- void (*mark_method)(xmlNodePtr) = NULL ;
1665
2010
 
1666
2011
  assert(c_node);
1667
2012
 
@@ -1669,11 +2014,9 @@ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1669
2014
  return DOC_RUBY_OBJECT(c_node->doc);
1670
2015
  }
1671
2016
 
1672
- /* It's OK if the node doesn't have a fully-realized document (as in XML::Reader). */
1673
- /* see https://github.com/sparklemotion/nokogiri/issues/95 */
1674
- /* and https://github.com/sparklemotion/nokogiri/issues/439 */
1675
2017
  c_doc = c_node->doc;
1676
- if (c_doc->type == XML_DOCUMENT_FRAG_NODE) { c_doc = c_doc->doc; }
2018
+
2019
+ // Nodes yielded from XML::Reader don't have a fully-realized Document
1677
2020
  node_has_a_document = DOC_RUBY_OBJECT_TEST(c_doc);
1678
2021
 
1679
2022
  if (c_node->_private && node_has_a_document) {
@@ -1682,50 +2025,48 @@ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1682
2025
 
1683
2026
  if (!RTEST(rb_class)) {
1684
2027
  switch (c_node->type) {
1685
- case XML_ELEMENT_NODE:
1686
- rb_class = cNokogiriXmlElement;
1687
- break;
1688
- case XML_TEXT_NODE:
1689
- rb_class = cNokogiriXmlText;
1690
- break;
1691
- case XML_ATTRIBUTE_NODE:
1692
- rb_class = cNokogiriXmlAttr;
1693
- break;
1694
- case XML_ENTITY_REF_NODE:
1695
- rb_class = cNokogiriXmlEntityReference;
1696
- break;
1697
- case XML_COMMENT_NODE:
1698
- rb_class = cNokogiriXmlComment;
1699
- break;
1700
- case XML_DOCUMENT_FRAG_NODE:
1701
- rb_class = cNokogiriXmlDocumentFragment;
1702
- break;
1703
- case XML_PI_NODE:
1704
- rb_class = cNokogiriXmlProcessingInstruction;
1705
- break;
1706
- case XML_ENTITY_DECL:
1707
- rb_class = cNokogiriXmlEntityDecl;
1708
- break;
1709
- case XML_CDATA_SECTION_NODE:
1710
- rb_class = cNokogiriXmlCData;
1711
- break;
1712
- case XML_DTD_NODE:
1713
- rb_class = cNokogiriXmlDtd;
1714
- break;
1715
- case XML_ATTRIBUTE_DECL:
1716
- rb_class = cNokogiriXmlAttributeDecl;
1717
- break;
1718
- case XML_ELEMENT_DECL:
1719
- rb_class = cNokogiriXmlElementDecl;
1720
- break;
1721
- default:
1722
- rb_class = cNokogiriXmlNode;
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;
1723
2066
  }
1724
2067
  }
1725
2068
 
1726
- mark_method = node_has_a_document ? mark : NULL ;
1727
-
1728
- rb_node = Data_Wrap_Struct(rb_class, mark_method, debug_node_dealloc, c_node) ;
2069
+ rb_node = TypedData_Wrap_Struct(rb_class, &nokogiri_node_type, c_node) ;
1729
2070
  c_node->_private = (void *)rb_node;
1730
2071
 
1731
2072
  if (node_has_a_document) {
@@ -1762,63 +2103,63 @@ noko_init_xml_node()
1762
2103
  {
1763
2104
  cNokogiriXmlNode = rb_define_class_under(mNokogiriXml, "Node", rb_cObject);
1764
2105
 
2106
+ rb_undef_alloc_func(cNokogiriXmlNode);
2107
+
1765
2108
  rb_define_singleton_method(cNokogiriXmlNode, "new", rb_xml_node_new, -1);
1766
2109
 
1767
- rb_define_method(cNokogiriXmlNode, "add_namespace_definition", add_namespace_definition, 2);
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);
1768
2140
  rb_define_method(cNokogiriXmlNode, "node_name", get_name, 0);
1769
- rb_define_method(cNokogiriXmlNode, "document", document, 0);
1770
2141
  rb_define_method(cNokogiriXmlNode, "node_name=", set_name, 1);
2142
+ rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
1771
2143
  rb_define_method(cNokogiriXmlNode, "parent", get_parent, 0);
1772
- rb_define_method(cNokogiriXmlNode, "child", child, 0);
1773
- rb_define_method(cNokogiriXmlNode, "first_element_child", first_element_child, 0);
1774
- rb_define_method(cNokogiriXmlNode, "last_element_child", last_element_child, 0);
1775
- rb_define_method(cNokogiriXmlNode, "children", children, 0);
1776
- rb_define_method(cNokogiriXmlNode, "element_children", element_children, 0);
1777
- rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
1778
- rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
1779
- rb_define_method(cNokogiriXmlNode, "next_element", next_element, 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);
1780
2146
  rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
1781
- rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
1782
- rb_define_method(cNokogiriXmlNode, "path", path, 0);
1783
- rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
1784
- rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
1785
- rb_define_method(cNokogiriXmlNode, "blank?", blank_eh, 0);
1786
- rb_define_method(cNokogiriXmlNode, "attribute_nodes", attribute_nodes, 0);
1787
- rb_define_method(cNokogiriXmlNode, "attribute", attr, 1);
1788
- rb_define_method(cNokogiriXmlNode, "attribute_with_ns", attribute_with_ns, 2);
1789
- rb_define_method(cNokogiriXmlNode, "namespace", noko_xml_node_namespace, 0);
1790
- rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
1791
- rb_define_method(cNokogiriXmlNode, "namespace_scopes", namespace_scopes, 0);
1792
- rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
1793
- rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
2147
+ rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
1794
2148
  rb_define_method(cNokogiriXmlNode, "unlink", unlink_node, 0);
1795
- rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
1796
- rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
1797
- rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
1798
- rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
1799
- rb_define_method(cNokogiriXmlNode, "pointer_id", pointer_id, 0);
1800
- rb_define_method(cNokogiriXmlNode, "line", line, 0);
1801
- rb_define_method(cNokogiriXmlNode, "line=", set_line, 1);
1802
- rb_define_method(cNokogiriXmlNode, "content", get_native_content, 0);
1803
- rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
1804
- rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
1805
- rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
1806
2149
 
1807
- rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
1808
- rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
1809
2150
  rb_define_private_method(cNokogiriXmlNode, "add_child_node", add_child, 1);
1810
- rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
1811
2151
  rb_define_private_method(cNokogiriXmlNode, "add_next_sibling_node", add_next_sibling, 1);
1812
- rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
2152
+ rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
2153
+ rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
1813
2154
  rb_define_private_method(cNokogiriXmlNode, "dump_html", dump_html, 0);
1814
- rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
1815
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);
1816
2160
  rb_define_private_method(cNokogiriXmlNode, "set", set, 2);
1817
2161
  rb_define_private_method(cNokogiriXmlNode, "set_namespace", set_namespace, 1);
1818
- rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
1819
2162
 
1820
2163
  id_decorate = rb_intern("decorate");
1821
2164
  id_decorate_bang = rb_intern("decorate!");
1822
2165
  }
1823
-
1824
- /* vim: set noet sw=4 sws=4 */