nokogiri 1.5.10 → 1.12.5

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 (328) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE-DEPENDENCIES.md +1903 -0
  4. data/LICENSE.md +9 -0
  5. data/README.md +278 -0
  6. data/bin/nokogiri +50 -10
  7. data/dependencies.yml +74 -0
  8. data/ext/nokogiri/depend +38 -358
  9. data/ext/nokogiri/extconf.rb +944 -100
  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 +120 -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 +232 -87
  18. data/ext/nokogiri/nokogiri.h +188 -129
  19. data/ext/nokogiri/test_global_handlers.c +40 -0
  20. data/ext/nokogiri/xml_attr.c +49 -40
  21. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  22. data/ext/nokogiri/xml_cdata.c +24 -23
  23. data/ext/nokogiri/xml_comment.c +29 -21
  24. data/ext/nokogiri/xml_document.c +305 -201
  25. data/ext/nokogiri/xml_document_fragment.c +13 -15
  26. data/ext/nokogiri/xml_dtd.c +54 -48
  27. data/ext/nokogiri/xml_element_content.c +31 -26
  28. data/ext/nokogiri/xml_element_decl.c +22 -22
  29. data/ext/nokogiri/xml_encoding_handler.c +30 -19
  30. data/ext/nokogiri/xml_entity_decl.c +32 -30
  31. data/ext/nokogiri/xml_entity_reference.c +16 -18
  32. data/ext/nokogiri/xml_namespace.c +74 -32
  33. data/ext/nokogiri/xml_node.c +808 -503
  34. data/ext/nokogiri/xml_node_set.c +239 -208
  35. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  36. data/ext/nokogiri/xml_reader.c +198 -186
  37. data/ext/nokogiri/xml_relax_ng.c +52 -28
  38. data/ext/nokogiri/xml_sax_parser.c +123 -125
  39. data/ext/nokogiri/xml_sax_parser_context.c +138 -79
  40. data/ext/nokogiri/xml_sax_push_parser.c +88 -35
  41. data/ext/nokogiri/xml_schema.c +112 -33
  42. data/ext/nokogiri/xml_syntax_error.c +50 -23
  43. data/ext/nokogiri/xml_text.c +14 -18
  44. data/ext/nokogiri/xml_xpath_context.c +162 -98
  45. data/ext/nokogiri/xslt_stylesheet.c +162 -168
  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 +4886 -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/css/node.rb +1 -50
  92. data/lib/nokogiri/css/parser.rb +317 -286
  93. data/lib/nokogiri/css/parser.y +57 -43
  94. data/lib/nokogiri/css/parser_extras.rb +39 -36
  95. data/lib/nokogiri/css/syntax_error.rb +2 -1
  96. data/lib/nokogiri/css/tokenizer.rb +105 -103
  97. data/lib/nokogiri/css/tokenizer.rex +5 -5
  98. data/lib/nokogiri/css/xpath_visitor.rb +137 -48
  99. data/lib/nokogiri/css.rb +15 -14
  100. data/lib/nokogiri/decorators/slop.rb +13 -5
  101. data/lib/nokogiri/extension.rb +31 -0
  102. data/lib/nokogiri/gumbo.rb +14 -0
  103. data/lib/nokogiri/html.rb +32 -27
  104. data/lib/nokogiri/{html → html4}/builder.rb +3 -2
  105. data/lib/nokogiri/{html → html4}/document.rb +118 -50
  106. data/lib/nokogiri/{html → html4}/document_fragment.rb +20 -11
  107. data/lib/nokogiri/{html → html4}/element_description.rb +2 -1
  108. data/lib/nokogiri/{html → html4}/element_description_defaults.rb +2 -1
  109. data/lib/nokogiri/{html → html4}/entity_lookup.rb +2 -1
  110. data/lib/nokogiri/{html → html4}/sax/parser.rb +22 -14
  111. data/lib/nokogiri/html4/sax/parser_context.rb +19 -0
  112. data/lib/nokogiri/html4/sax/push_parser.rb +37 -0
  113. data/lib/nokogiri/html4.rb +40 -0
  114. data/lib/nokogiri/html5/document.rb +74 -0
  115. data/lib/nokogiri/html5/document_fragment.rb +80 -0
  116. data/lib/nokogiri/html5/node.rb +93 -0
  117. data/lib/nokogiri/html5.rb +473 -0
  118. data/lib/nokogiri/jruby/dependencies.rb +20 -0
  119. data/lib/nokogiri/syntax_error.rb +1 -0
  120. data/lib/nokogiri/version/constant.rb +5 -0
  121. data/lib/nokogiri/version/info.rb +215 -0
  122. data/lib/nokogiri/version.rb +3 -91
  123. data/lib/nokogiri/xml/attr.rb +1 -0
  124. data/lib/nokogiri/xml/attribute_decl.rb +1 -0
  125. data/lib/nokogiri/xml/builder.rb +75 -33
  126. data/lib/nokogiri/xml/cdata.rb +1 -0
  127. data/lib/nokogiri/xml/character_data.rb +1 -0
  128. data/lib/nokogiri/xml/document.rb +157 -54
  129. data/lib/nokogiri/xml/document_fragment.rb +55 -8
  130. data/lib/nokogiri/xml/dtd.rb +15 -4
  131. data/lib/nokogiri/xml/element_content.rb +1 -0
  132. data/lib/nokogiri/xml/element_decl.rb +1 -0
  133. data/lib/nokogiri/xml/entity_decl.rb +1 -0
  134. data/lib/nokogiri/xml/entity_reference.rb +19 -0
  135. data/lib/nokogiri/xml/namespace.rb +1 -0
  136. data/lib/nokogiri/xml/node/save_options.rb +2 -1
  137. data/lib/nokogiri/xml/node.rb +712 -431
  138. data/lib/nokogiri/xml/node_set.rb +140 -123
  139. data/lib/nokogiri/xml/notation.rb +1 -0
  140. data/lib/nokogiri/xml/parse_options.rb +31 -0
  141. data/lib/nokogiri/xml/pp/character_data.rb +1 -0
  142. data/lib/nokogiri/xml/pp/node.rb +1 -0
  143. data/lib/nokogiri/xml/pp.rb +3 -2
  144. data/lib/nokogiri/xml/processing_instruction.rb +1 -0
  145. data/lib/nokogiri/xml/reader.rb +9 -12
  146. data/lib/nokogiri/xml/relax_ng.rb +7 -2
  147. data/lib/nokogiri/xml/sax/document.rb +25 -30
  148. data/lib/nokogiri/xml/sax/parser.rb +8 -8
  149. data/lib/nokogiri/xml/sax/parser_context.rb +1 -0
  150. data/lib/nokogiri/xml/sax/push_parser.rb +1 -0
  151. data/lib/nokogiri/xml/sax.rb +5 -4
  152. data/lib/nokogiri/xml/schema.rb +13 -4
  153. data/lib/nokogiri/xml/searchable.rb +239 -0
  154. data/lib/nokogiri/xml/syntax_error.rb +25 -1
  155. data/lib/nokogiri/xml/text.rb +1 -0
  156. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  157. data/lib/nokogiri/xml/xpath.rb +4 -5
  158. data/lib/nokogiri/xml/xpath_context.rb +1 -0
  159. data/lib/nokogiri/xml.rb +37 -35
  160. data/lib/nokogiri/xslt/stylesheet.rb +2 -1
  161. data/lib/nokogiri/xslt.rb +17 -16
  162. data/lib/nokogiri.rb +55 -58
  163. data/lib/xsd/xmlparser/nokogiri.rb +1 -0
  164. data/patches/libxml2/0001-Remove-script-macro-support.patch +40 -0
  165. data/patches/libxml2/0002-Update-entities-to-remove-handling-of-ssi.patch +44 -0
  166. data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +25 -0
  167. data/patches/libxml2/0004-use-glibc-strlen.patch +53 -0
  168. data/patches/libxml2/0005-avoid-isnan-isinf.patch +81 -0
  169. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +2511 -0
  170. data/patches/libxml2/0007-Fix-XPath-recursion-limit.patch +31 -0
  171. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2511 -0
  172. data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +19 -0
  173. data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
  174. data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
  175. metadata +307 -459
  176. data/.autotest +0 -26
  177. data/.gemtest +0 -0
  178. data/CHANGELOG.ja.rdoc +0 -785
  179. data/CHANGELOG.rdoc +0 -783
  180. data/C_CODING_STYLE.rdoc +0 -33
  181. data/Manifest.txt +0 -303
  182. data/README.ja.rdoc +0 -106
  183. data/README.rdoc +0 -175
  184. data/ROADMAP.md +0 -90
  185. data/Rakefile +0 -228
  186. data/STANDARD_RESPONSES.md +0 -47
  187. data/Y_U_NO_GEMSPEC.md +0 -155
  188. data/build_all +0 -105
  189. data/ext/nokogiri/html_document.c +0 -170
  190. data/ext/nokogiri/html_document.h +0 -10
  191. data/ext/nokogiri/html_element_description.c +0 -279
  192. data/ext/nokogiri/html_element_description.h +0 -10
  193. data/ext/nokogiri/html_entity_lookup.c +0 -32
  194. data/ext/nokogiri/html_entity_lookup.h +0 -8
  195. data/ext/nokogiri/html_sax_parser_context.c +0 -116
  196. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  197. data/ext/nokogiri/html_sax_push_parser.c +0 -87
  198. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  199. data/ext/nokogiri/xml_attr.h +0 -9
  200. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  201. data/ext/nokogiri/xml_cdata.h +0 -9
  202. data/ext/nokogiri/xml_comment.h +0 -9
  203. data/ext/nokogiri/xml_document.h +0 -23
  204. data/ext/nokogiri/xml_document_fragment.h +0 -10
  205. data/ext/nokogiri/xml_dtd.h +0 -10
  206. data/ext/nokogiri/xml_element_content.h +0 -10
  207. data/ext/nokogiri/xml_element_decl.h +0 -9
  208. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  209. data/ext/nokogiri/xml_entity_decl.h +0 -10
  210. data/ext/nokogiri/xml_entity_reference.h +0 -9
  211. data/ext/nokogiri/xml_io.c +0 -56
  212. data/ext/nokogiri/xml_io.h +0 -11
  213. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  214. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  215. data/ext/nokogiri/xml_namespace.h +0 -13
  216. data/ext/nokogiri/xml_node.h +0 -13
  217. data/ext/nokogiri/xml_node_set.h +0 -14
  218. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  219. data/ext/nokogiri/xml_reader.h +0 -10
  220. data/ext/nokogiri/xml_relax_ng.h +0 -9
  221. data/ext/nokogiri/xml_sax_parser.h +0 -39
  222. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  223. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  224. data/ext/nokogiri/xml_schema.h +0 -9
  225. data/ext/nokogiri/xml_syntax_error.h +0 -13
  226. data/ext/nokogiri/xml_text.h +0 -9
  227. data/ext/nokogiri/xml_xpath_context.h +0 -10
  228. data/ext/nokogiri/xslt_stylesheet.h +0 -14
  229. data/lib/nokogiri/html/sax/parser_context.rb +0 -16
  230. data/lib/nokogiri/html/sax/push_parser.rb +0 -16
  231. data/tasks/cross_compile.rb +0 -150
  232. data/tasks/nokogiri.org.rb +0 -24
  233. data/tasks/test.rb +0 -95
  234. data/test/css/test_nthiness.rb +0 -159
  235. data/test/css/test_parser.rb +0 -341
  236. data/test/css/test_tokenizer.rb +0 -198
  237. data/test/css/test_xpath_visitor.rb +0 -91
  238. data/test/decorators/test_slop.rb +0 -16
  239. data/test/files/2ch.html +0 -108
  240. data/test/files/address_book.rlx +0 -12
  241. data/test/files/address_book.xml +0 -10
  242. data/test/files/bar/bar.xsd +0 -4
  243. data/test/files/dont_hurt_em_why.xml +0 -422
  244. data/test/files/encoding.html +0 -82
  245. data/test/files/encoding.xhtml +0 -84
  246. data/test/files/exslt.xml +0 -8
  247. data/test/files/exslt.xslt +0 -35
  248. data/test/files/foo/foo.xsd +0 -4
  249. data/test/files/metacharset.html +0 -10
  250. data/test/files/noencoding.html +0 -47
  251. data/test/files/po.xml +0 -32
  252. data/test/files/po.xsd +0 -66
  253. data/test/files/shift_jis.html +0 -10
  254. data/test/files/shift_jis.xml +0 -5
  255. data/test/files/snuggles.xml +0 -3
  256. data/test/files/staff.dtd +0 -10
  257. data/test/files/staff.xml +0 -59
  258. data/test/files/staff.xslt +0 -32
  259. data/test/files/test_document_url/bar.xml +0 -2
  260. data/test/files/test_document_url/document.dtd +0 -4
  261. data/test/files/test_document_url/document.xml +0 -6
  262. data/test/files/tlm.html +0 -850
  263. data/test/files/to_be_xincluded.xml +0 -2
  264. data/test/files/valid_bar.xml +0 -2
  265. data/test/files/xinclude.xml +0 -4
  266. data/test/helper.rb +0 -154
  267. data/test/html/sax/test_parser.rb +0 -141
  268. data/test/html/sax/test_parser_context.rb +0 -46
  269. data/test/html/test_builder.rb +0 -164
  270. data/test/html/test_document.rb +0 -552
  271. data/test/html/test_document_encoding.rb +0 -138
  272. data/test/html/test_document_fragment.rb +0 -261
  273. data/test/html/test_element_description.rb +0 -105
  274. data/test/html/test_named_characters.rb +0 -14
  275. data/test/html/test_node.rb +0 -196
  276. data/test/html/test_node_encoding.rb +0 -27
  277. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +0 -14
  278. data/test/namespaces/test_namespaces_in_builder_doc.rb +0 -75
  279. data/test/namespaces/test_namespaces_in_created_doc.rb +0 -75
  280. data/test/namespaces/test_namespaces_in_parsed_doc.rb +0 -66
  281. data/test/test_convert_xpath.rb +0 -135
  282. data/test/test_css_cache.rb +0 -45
  283. data/test/test_encoding_handler.rb +0 -46
  284. data/test/test_memory_leak.rb +0 -156
  285. data/test/test_nokogiri.rb +0 -132
  286. data/test/test_reader.rb +0 -555
  287. data/test/test_soap4r_sax.rb +0 -52
  288. data/test/test_xslt_transforms.rb +0 -254
  289. data/test/xml/node/test_save_options.rb +0 -28
  290. data/test/xml/node/test_subclass.rb +0 -44
  291. data/test/xml/sax/test_parser.rb +0 -366
  292. data/test/xml/sax/test_parser_context.rb +0 -106
  293. data/test/xml/sax/test_push_parser.rb +0 -157
  294. data/test/xml/test_attr.rb +0 -64
  295. data/test/xml/test_attribute_decl.rb +0 -86
  296. data/test/xml/test_builder.rb +0 -306
  297. data/test/xml/test_c14n.rb +0 -151
  298. data/test/xml/test_cdata.rb +0 -48
  299. data/test/xml/test_comment.rb +0 -29
  300. data/test/xml/test_document.rb +0 -828
  301. data/test/xml/test_document_encoding.rb +0 -28
  302. data/test/xml/test_document_fragment.rb +0 -223
  303. data/test/xml/test_dtd.rb +0 -103
  304. data/test/xml/test_dtd_encoding.rb +0 -33
  305. data/test/xml/test_element_content.rb +0 -56
  306. data/test/xml/test_element_decl.rb +0 -73
  307. data/test/xml/test_entity_decl.rb +0 -122
  308. data/test/xml/test_entity_reference.rb +0 -245
  309. data/test/xml/test_namespace.rb +0 -95
  310. data/test/xml/test_node.rb +0 -1137
  311. data/test/xml/test_node_attributes.rb +0 -96
  312. data/test/xml/test_node_encoding.rb +0 -107
  313. data/test/xml/test_node_inheritance.rb +0 -32
  314. data/test/xml/test_node_reparenting.rb +0 -374
  315. data/test/xml/test_node_set.rb +0 -755
  316. data/test/xml/test_parse_options.rb +0 -64
  317. data/test/xml/test_processing_instruction.rb +0 -30
  318. data/test/xml/test_reader_encoding.rb +0 -142
  319. data/test/xml/test_relax_ng.rb +0 -60
  320. data/test/xml/test_schema.rb +0 -103
  321. data/test/xml/test_syntax_error.rb +0 -12
  322. data/test/xml/test_text.rb +0 -45
  323. data/test/xml/test_unparented_node.rb +0 -422
  324. data/test/xml/test_xinclude.rb +0 -83
  325. data/test/xml/test_xpath.rb +0 -295
  326. data/test/xslt/test_custom_functions.rb +0 -133
  327. data/test/xslt/test_exception_handling.rb +0 -37
  328. data/test_all +0 -81
@@ -1,9 +1,12 @@
1
- #include <xml_node.h>
1
+ #include <nokogiri.h>
2
2
 
3
- static ID decorate, decorate_bang;
3
+ VALUE cNokogiriXmlNode ;
4
+
5
+ static ID id_decorate, id_decorate_bang;
4
6
 
5
7
  #ifdef DEBUG
6
- static void debug_node_dealloc(xmlNodePtr x)
8
+ static void
9
+ debug_node_dealloc(xmlNodePtr x)
7
10
  {
8
11
  NOKOGIRI_DEBUG_START(x)
9
12
  NOKOGIRI_DEBUG_END(x)
@@ -12,70 +15,87 @@ static void debug_node_dealloc(xmlNodePtr x)
12
15
  # define debug_node_dealloc 0
13
16
  #endif
14
17
 
15
- static void mark(xmlNodePtr node)
18
+ static void
19
+ mark(xmlNodePtr node)
16
20
  {
17
- rb_gc_mark(DOC_RUBY_OBJECT(node->doc));
21
+ xmlDocPtr doc = node->doc;
22
+ if (doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
23
+ if (DOC_RUBY_OBJECT_TEST(doc)) {
24
+ rb_gc_mark(DOC_RUBY_OBJECT(doc));
25
+ }
26
+ } else if (node->doc->_private) {
27
+ rb_gc_mark((VALUE)doc->_private);
28
+ }
18
29
  }
19
30
 
20
31
  /* :nodoc: */
21
- typedef xmlNodePtr (*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
32
+ typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
22
33
 
23
34
  /* :nodoc: */
24
- static void relink_namespace(xmlNodePtr reparented)
35
+ static void
36
+ relink_namespace(xmlNodePtr reparented)
25
37
  {
26
- xmlChar *name, *prefix;
27
38
  xmlNodePtr child;
28
- xmlNsPtr ns;
39
+ xmlAttrPtr attr;
29
40
 
30
41
  if (reparented->type != XML_ATTRIBUTE_NODE &&
31
- reparented->type != XML_ELEMENT_NODE) return;
42
+ reparented->type != XML_ELEMENT_NODE) { return; }
32
43
 
33
44
  if (reparented->ns == NULL || reparented->ns->prefix == NULL) {
45
+ xmlNsPtr ns = NULL;
46
+ xmlChar *name = NULL, *prefix = NULL;
47
+
34
48
  name = xmlSplitQName2(reparented->name, &prefix);
35
49
 
36
- if(reparented->type == XML_ATTRIBUTE_NODE) {
37
- if (prefix == NULL || strcmp((char*)prefix, XMLNS_PREFIX) == 0) return;
50
+ if (reparented->type == XML_ATTRIBUTE_NODE) {
51
+ if (prefix == NULL || strcmp((char *)prefix, XMLNS_PREFIX) == 0) {
52
+ xmlFree(name);
53
+ xmlFree(prefix);
54
+ return;
55
+ }
38
56
  }
39
57
 
40
58
  ns = xmlSearchNs(reparented->doc, reparented, prefix);
41
59
 
42
- if (ns == NULL && reparented->parent) {
43
- ns = xmlSearchNs(reparented->doc, reparented->parent, prefix);
44
- }
45
-
46
60
  if (ns != NULL) {
47
61
  xmlNodeSetName(reparented, name);
48
62
  xmlSetNs(reparented, ns);
49
63
  }
64
+
65
+ xmlFree(name);
66
+ xmlFree(prefix);
50
67
  }
51
68
 
52
69
  /* Avoid segv when relinking against unlinked nodes. */
53
- if (reparented->type != XML_ELEMENT_NODE || !reparented->parent) return;
70
+ if (reparented->type != XML_ELEMENT_NODE || !reparented->parent) { return; }
54
71
 
55
72
  /* Make sure that our reparented node has the correct namespaces */
56
- if(!reparented->ns && reparented->doc != (xmlDocPtr)reparented->parent)
73
+ if (!reparented->ns &&
74
+ (reparented->doc != (xmlDocPtr)reparented->parent) &&
75
+ (rb_iv_get(DOC_RUBY_OBJECT(reparented->doc), "@namespace_inheritance") == Qtrue)) {
57
76
  xmlSetNs(reparented, reparented->parent->ns);
77
+ }
58
78
 
59
79
  /* Search our parents for an existing definition */
60
- if(reparented->nsDef) {
80
+ if (reparented->nsDef) {
61
81
  xmlNsPtr curr = reparented->nsDef;
62
82
  xmlNsPtr prev = NULL;
63
83
 
64
- while(curr) {
84
+ while (curr) {
65
85
  xmlNsPtr ns = xmlSearchNsByHref(
66
- reparented->doc,
67
- reparented->parent,
68
- curr->href
69
- );
86
+ reparented->doc,
87
+ reparented->parent,
88
+ curr->href
89
+ );
70
90
  /* If we find the namespace is already declared, remove it from this
71
91
  * definition list. */
72
- if(ns && ns != curr) {
92
+ if (ns && ns != curr && xmlStrEqual(ns->prefix, curr->prefix)) {
73
93
  if (prev) {
74
94
  prev->next = curr->next;
75
95
  } else {
76
96
  reparented->nsDef = curr->next;
77
97
  }
78
- nokogiri_root_nsdef(curr, reparented->doc);
98
+ noko_xml_document_pin_namespace(curr, reparented->doc);
79
99
  } else {
80
100
  prev = curr;
81
101
  }
@@ -83,29 +103,49 @@ static void relink_namespace(xmlNodePtr reparented)
83
103
  }
84
104
  }
85
105
 
106
+ /*
107
+ * Search our parents for an existing definition of current namespace,
108
+ * because the definition it's pointing to may have just been removed nsDef.
109
+ *
110
+ * And although that would technically probably be OK, I'd feel better if we
111
+ * referred to a namespace that's still present in a node's nsDef somewhere
112
+ * in the doc.
113
+ */
114
+ if (reparented->ns) {
115
+ xmlNsPtr ns = xmlSearchNs(reparented->doc, reparented, reparented->ns->prefix);
116
+ if (ns
117
+ && ns != reparented->ns
118
+ && xmlStrEqual(ns->prefix, reparented->ns->prefix)
119
+ && xmlStrEqual(ns->href, reparented->ns->href)
120
+ ) {
121
+ xmlSetNs(reparented, ns);
122
+ }
123
+ }
124
+
86
125
  /* Only walk all children if there actually is a namespace we need to */
87
126
  /* reparent. */
88
- if(NULL == reparented->ns) return;
127
+ if (NULL == reparented->ns) { return; }
89
128
 
90
129
  /* When a node gets reparented, walk it's children to make sure that */
91
130
  /* their namespaces are reparented as well. */
92
131
  child = reparented->children;
93
- while(NULL != child) {
132
+ while (NULL != child) {
94
133
  relink_namespace(child);
95
134
  child = child->next;
96
135
  }
97
136
 
98
137
  if (reparented->type == XML_ELEMENT_NODE) {
99
- child = (xmlNodePtr)((xmlElementPtr)reparented)->attributes;
100
- while(NULL != child) {
101
- relink_namespace(child);
102
- child = child->next;
138
+ attr = reparented->properties;
139
+ while (NULL != attr) {
140
+ relink_namespace((xmlNodePtr)attr);
141
+ attr = attr->next;
103
142
  }
104
143
  }
105
144
  }
106
145
 
107
146
  /* :nodoc: */
108
- static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
147
+ static xmlNodePtr
148
+ xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
109
149
  {
110
150
  xmlNodePtr retval ;
111
151
 
@@ -129,23 +169,97 @@ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
129
169
  }
130
170
 
131
171
  /* :nodoc: */
132
- static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
172
+ static VALUE
173
+ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
133
174
  {
134
175
  VALUE reparented_obj ;
135
- xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text ;
176
+ xmlNodePtr reparentee, original_reparentee, pivot, reparented, next_text, new_next_text, parent ;
177
+ int original_ns_prefix_is_default = 0 ;
136
178
 
137
- if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode))
179
+ if (!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode)) {
138
180
  rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
139
- if(rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument))
181
+ }
182
+ if (rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument)) {
140
183
  rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
184
+ }
141
185
 
142
186
  Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
143
187
  Data_Get_Struct(pivot_obj, xmlNode, pivot);
144
188
 
145
- if(XML_DOCUMENT_NODE == reparentee->type || XML_HTML_DOCUMENT_NODE == reparentee->type)
146
- rb_raise(rb_eArgError, "cannot reparent a document node");
189
+ /*
190
+ * Check if nodes given are appropriate to have a parent-child
191
+ * relationship, based on the DOM specification.
192
+ *
193
+ * cf. http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1590626202
194
+ */
195
+ if (prf == xmlAddChild) {
196
+ parent = pivot;
197
+ } else {
198
+ parent = pivot->parent;
199
+ }
200
+
201
+ if (parent) {
202
+ switch (parent->type) {
203
+ case XML_DOCUMENT_NODE:
204
+ case XML_HTML_DOCUMENT_NODE:
205
+ switch (reparentee->type) {
206
+ case XML_ELEMENT_NODE:
207
+ case XML_PI_NODE:
208
+ case XML_COMMENT_NODE:
209
+ case XML_DOCUMENT_TYPE_NODE:
210
+ /*
211
+ * The DOM specification says no to adding text-like nodes
212
+ * directly to a document, but we allow it for compatibility.
213
+ */
214
+ case XML_TEXT_NODE:
215
+ case XML_CDATA_SECTION_NODE:
216
+ case XML_ENTITY_REF_NODE:
217
+ goto ok;
218
+ default:
219
+ break;
220
+ }
221
+ break;
222
+ case XML_DOCUMENT_FRAG_NODE:
223
+ case XML_ENTITY_REF_NODE:
224
+ case XML_ELEMENT_NODE:
225
+ switch (reparentee->type) {
226
+ case XML_ELEMENT_NODE:
227
+ case XML_PI_NODE:
228
+ case XML_COMMENT_NODE:
229
+ case XML_TEXT_NODE:
230
+ case XML_CDATA_SECTION_NODE:
231
+ case XML_ENTITY_REF_NODE:
232
+ goto ok;
233
+ default:
234
+ break;
235
+ }
236
+ break;
237
+ case XML_ATTRIBUTE_NODE:
238
+ switch (reparentee->type) {
239
+ case XML_TEXT_NODE:
240
+ case XML_ENTITY_REF_NODE:
241
+ goto ok;
242
+ default:
243
+ break;
244
+ }
245
+ break;
246
+ case XML_TEXT_NODE:
247
+ /*
248
+ * xmlAddChild() breaks the DOM specification in that it allows
249
+ * adding a text node to another, in which case text nodes are
250
+ * coalesced, but since our JRuby version does not support such
251
+ * operation, we should inhibit it.
252
+ */
253
+ break;
254
+ default:
255
+ break;
256
+ }
257
+
258
+ rb_raise(rb_eArgError, "cannot reparent %s there", rb_obj_classname(reparentee_obj));
259
+ }
147
260
 
148
- xmlUnlinkNode(reparentee);
261
+ ok:
262
+ original_reparentee = reparentee;
149
263
 
150
264
  if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
151
265
  /*
@@ -164,12 +278,46 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
164
278
  * uninteresting libxml2 implementation detail). as a result, we cannot
165
279
  * reparent the actual reparentee, so we reparent a duplicate.
166
280
  */
167
- nokogiri_root_node(reparentee);
281
+ if (reparentee->type == XML_TEXT_NODE && reparentee->_private) {
282
+ /*
283
+ * additionally, since we know this C struct isn't going to be related to
284
+ * a Ruby object anymore, let's break the relationship on this end as
285
+ * well.
286
+ *
287
+ * this is not absolutely necessary unless libxml-ruby is also in effect,
288
+ * in which case its global callback `rxml_node_deregisterNode` will try
289
+ * to do things to our data.
290
+ *
291
+ * for more details on this particular (and particularly nasty) edge
292
+ * case, see:
293
+ *
294
+ * https://github.com/sparklemotion/nokogiri/issues/1426
295
+ */
296
+ reparentee->_private = NULL ;
297
+ }
298
+
299
+ if (reparentee->ns != NULL && reparentee->ns->prefix == NULL) {
300
+ original_ns_prefix_is_default = 1;
301
+ }
302
+
303
+ noko_xml_document_pin_node(reparentee);
304
+
168
305
  if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
169
306
  rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
170
307
  }
308
+
309
+ if (original_ns_prefix_is_default && reparentee->ns != NULL && reparentee->ns->prefix != NULL) {
310
+ /*
311
+ * issue #391, where new node's prefix may become the string "default"
312
+ * see libxml2 tree.c xmlNewReconciliedNs which implements this behavior.
313
+ */
314
+ xmlFree(DISCARD_CONST_QUAL_XMLCHAR(reparentee->ns->prefix));
315
+ reparentee->ns->prefix = NULL;
316
+ }
171
317
  }
172
318
 
319
+ xmlUnlinkNode(original_reparentee);
320
+
173
321
  if (prf != xmlAddPrevSibling && prf != xmlAddNextSibling
174
322
  && reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
175
323
  /*
@@ -194,12 +342,12 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
194
342
  new_next_text = xmlDocCopyNode(next_text, pivot->doc, 1) ;
195
343
 
196
344
  xmlUnlinkNode(next_text);
197
- nokogiri_root_node(next_text);
345
+ noko_xml_document_pin_node(next_text);
198
346
 
199
347
  xmlAddNextSibling(pivot, new_next_text);
200
348
  }
201
349
 
202
- if(!(reparented = (*prf)(pivot, reparentee))) {
350
+ if (!(reparented = (*prf)(pivot, reparentee))) {
203
351
  rb_raise(rb_eRuntimeError, "Could not reparent node");
204
352
  }
205
353
 
@@ -212,9 +360,9 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
212
360
 
213
361
  relink_namespace(reparented);
214
362
 
215
- reparented_obj = Nokogiri_wrap_xml_node(Qnil, reparented);
363
+ reparented_obj = noko_xml_node_wrap(Qnil, reparented);
216
364
 
217
- rb_funcall(reparented_obj, decorate_bang, 0);
365
+ rb_funcall(reparented_obj, id_decorate_bang, 0);
218
366
 
219
367
  return reparented_obj ;
220
368
  }
@@ -226,7 +374,8 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
226
374
  *
227
375
  * Get the document for this Node
228
376
  */
229
- static VALUE document(VALUE self)
377
+ static VALUE
378
+ document(VALUE self)
230
379
  {
231
380
  xmlNodePtr node;
232
381
  Data_Get_Struct(self, xmlNode, node);
@@ -239,7 +388,8 @@ static VALUE document(VALUE self)
239
388
  *
240
389
  * Get the internal pointer number
241
390
  */
242
- static VALUE pointer_id(VALUE self)
391
+ static VALUE
392
+ pointer_id(VALUE self)
243
393
  {
244
394
  xmlNodePtr node;
245
395
  Data_Get_Struct(self, xmlNode, node);
@@ -253,7 +403,8 @@ static VALUE pointer_id(VALUE self)
253
403
  *
254
404
  * Encode any special characters in +string+
255
405
  */
256
- static VALUE encode_special_chars(VALUE self, VALUE string)
406
+ static VALUE
407
+ encode_special_chars(VALUE self, VALUE string)
257
408
  {
258
409
  xmlNodePtr node;
259
410
  xmlChar *encoded;
@@ -261,9 +412,9 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
261
412
 
262
413
  Data_Get_Struct(self, xmlNode, node);
263
414
  encoded = xmlEncodeSpecialChars(
264
- node->doc,
265
- (const xmlChar *)StringValuePtr(string)
266
- );
415
+ node->doc,
416
+ (const xmlChar *)StringValueCStr(string)
417
+ );
267
418
 
268
419
  encoded_str = NOKOGIRI_STR_NEW2(encoded);
269
420
  xmlFree(encoded);
@@ -283,7 +434,8 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
283
434
  * doc.create_internal_subset("chapter", nil, "chapter.dtd")
284
435
  * # => <!DOCTYPE chapter SYSTEM "chapter.dtd">
285
436
  */
286
- static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
437
+ static VALUE
438
+ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
287
439
  {
288
440
  xmlNodePtr node;
289
441
  xmlDocPtr doc;
@@ -293,19 +445,20 @@ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, V
293
445
 
294
446
  doc = node->doc;
295
447
 
296
- if(xmlGetIntSubset(doc))
448
+ if (xmlGetIntSubset(doc)) {
297
449
  rb_raise(rb_eRuntimeError, "Document already has an internal subset");
450
+ }
298
451
 
299
452
  dtd = xmlCreateIntSubset(
300
- doc,
301
- NIL_P(name) ? NULL : (const xmlChar *)StringValuePtr(name),
302
- NIL_P(external_id) ? NULL : (const xmlChar *)StringValuePtr(external_id),
303
- NIL_P(system_id) ? NULL : (const xmlChar *)StringValuePtr(system_id)
304
- );
453
+ doc,
454
+ NIL_P(name) ? NULL : (const xmlChar *)StringValueCStr(name),
455
+ NIL_P(external_id) ? NULL : (const xmlChar *)StringValueCStr(external_id),
456
+ NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
457
+ );
305
458
 
306
- if(!dtd) return Qnil;
459
+ if (!dtd) { return Qnil; }
307
460
 
308
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
461
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
309
462
  }
310
463
 
311
464
  /*
@@ -314,7 +467,8 @@ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, V
314
467
  *
315
468
  * Create an external subset
316
469
  */
317
- static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
470
+ static VALUE
471
+ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
318
472
  {
319
473
  xmlNodePtr node;
320
474
  xmlDocPtr doc;
@@ -324,19 +478,20 @@ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, V
324
478
 
325
479
  doc = node->doc;
326
480
 
327
- if(doc->extSubset)
481
+ if (doc->extSubset) {
328
482
  rb_raise(rb_eRuntimeError, "Document already has an external subset");
483
+ }
329
484
 
330
485
  dtd = xmlNewDtd(
331
- doc,
332
- NIL_P(name) ? NULL : (const xmlChar *)StringValuePtr(name),
333
- NIL_P(external_id) ? NULL : (const xmlChar *)StringValuePtr(external_id),
334
- NIL_P(system_id) ? NULL : (const xmlChar *)StringValuePtr(system_id)
335
- );
486
+ doc,
487
+ NIL_P(name) ? NULL : (const xmlChar *)StringValueCStr(name),
488
+ NIL_P(external_id) ? NULL : (const xmlChar *)StringValueCStr(external_id),
489
+ NIL_P(system_id) ? NULL : (const xmlChar *)StringValueCStr(system_id)
490
+ );
336
491
 
337
- if(!dtd) return Qnil;
492
+ if (!dtd) { return Qnil; }
338
493
 
339
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
494
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
340
495
  }
341
496
 
342
497
  /*
@@ -345,7 +500,8 @@ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, V
345
500
  *
346
501
  * Get the external subset
347
502
  */
348
- static VALUE external_subset(VALUE self)
503
+ static VALUE
504
+ external_subset(VALUE self)
349
505
  {
350
506
  xmlNodePtr node;
351
507
  xmlDocPtr doc;
@@ -353,14 +509,14 @@ static VALUE external_subset(VALUE self)
353
509
 
354
510
  Data_Get_Struct(self, xmlNode, node);
355
511
 
356
- if(!node->doc) return Qnil;
512
+ if (!node->doc) { return Qnil; }
357
513
 
358
514
  doc = node->doc;
359
515
  dtd = doc->extSubset;
360
516
 
361
- if(!dtd) return Qnil;
517
+ if (!dtd) { return Qnil; }
362
518
 
363
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
519
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
364
520
  }
365
521
 
366
522
  /*
@@ -369,7 +525,8 @@ static VALUE external_subset(VALUE self)
369
525
  *
370
526
  * Get the internal subset
371
527
  */
372
- static VALUE internal_subset(VALUE self)
528
+ static VALUE
529
+ internal_subset(VALUE self)
373
530
  {
374
531
  xmlNodePtr node;
375
532
  xmlDocPtr doc;
@@ -377,39 +534,58 @@ static VALUE internal_subset(VALUE self)
377
534
 
378
535
  Data_Get_Struct(self, xmlNode, node);
379
536
 
380
- if(!node->doc) return Qnil;
537
+ if (!node->doc) { return Qnil; }
381
538
 
382
539
  doc = node->doc;
383
540
  dtd = xmlGetIntSubset(doc);
384
541
 
385
- if(!dtd) return Qnil;
542
+ if (!dtd) { return Qnil; }
386
543
 
387
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
544
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)dtd);
388
545
  }
389
546
 
390
547
  /*
391
548
  * call-seq:
392
549
  * dup
550
+ * dup(depth)
551
+ * dup(depth, new_parent_doc)
393
552
  *
394
- * Copy this node. An optional depth may be passed in, but it defaults
395
- * to a deep copy. 0 is a shallow copy, 1 is a deep copy.
553
+ * Copy this node.
554
+ * An optional depth may be passed in. 0 is a shallow copy, 1 (the default) is a deep copy.
555
+ * An optional new_parent_doc may also be passed in, which will be the new
556
+ * node's parent document. Defaults to the current node's document.
557
+ * current document.
396
558
  */
397
- static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
559
+ static VALUE
560
+ duplicate_node(int argc, VALUE *argv, VALUE self)
398
561
  {
399
- VALUE level;
562
+ VALUE r_level, r_new_parent_doc;
563
+ int level;
564
+ int n_args;
565
+ xmlDocPtr new_parent_doc;
400
566
  xmlNodePtr node, dup;
401
567
 
402
- if(rb_scan_args(argc, argv, "01", &level) == 0)
403
- level = INT2NUM((long)1);
404
-
405
568
  Data_Get_Struct(self, xmlNode, node);
406
569
 
407
- dup = xmlDocCopyNode(node, node->doc, (int)NUM2INT(level));
408
- if(dup == NULL) return Qnil;
570
+ n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
571
+
572
+ if (n_args < 1) {
573
+ r_level = INT2NUM((long)1);
574
+ }
575
+ level = (int)NUM2INT(r_level);
576
+
577
+ if (n_args < 2) {
578
+ new_parent_doc = node->doc;
579
+ } else {
580
+ Data_Get_Struct(r_new_parent_doc, xmlDoc, new_parent_doc);
581
+ }
409
582
 
410
- nokogiri_root_node(dup);
583
+ dup = xmlDocCopyNode(node, new_parent_doc, level);
584
+ if (dup == NULL) { return Qnil; }
411
585
 
412
- return Nokogiri_wrap_xml_node(rb_obj_class(self), dup);
586
+ noko_xml_document_pin_node(dup);
587
+
588
+ return noko_xml_node_wrap(rb_obj_class(self), dup);
413
589
  }
414
590
 
415
591
  /*
@@ -418,12 +594,13 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
418
594
  *
419
595
  * Unlink this node from its current context.
420
596
  */
421
- static VALUE unlink_node(VALUE self)
597
+ static VALUE
598
+ unlink_node(VALUE self)
422
599
  {
423
600
  xmlNodePtr node;
424
601
  Data_Get_Struct(self, xmlNode, node);
425
602
  xmlUnlinkNode(node);
426
- nokogiri_root_node(node);
603
+ noko_xml_document_pin_node(node);
427
604
  return self;
428
605
  }
429
606
 
@@ -433,7 +610,8 @@ static VALUE unlink_node(VALUE self)
433
610
  *
434
611
  * Is this node blank?
435
612
  */
436
- static VALUE blank_eh(VALUE self)
613
+ static VALUE
614
+ blank_eh(VALUE self)
437
615
  {
438
616
  xmlNodePtr node;
439
617
  Data_Get_Struct(self, xmlNode, node);
@@ -446,15 +624,16 @@ static VALUE blank_eh(VALUE self)
446
624
  *
447
625
  * Returns the next sibling node
448
626
  */
449
- static VALUE next_sibling(VALUE self)
627
+ static VALUE
628
+ next_sibling(VALUE self)
450
629
  {
451
630
  xmlNodePtr node, sibling;
452
631
  Data_Get_Struct(self, xmlNode, node);
453
632
 
454
633
  sibling = node->next;
455
- if(!sibling) return Qnil;
634
+ if (!sibling) { return Qnil; }
456
635
 
457
- return Nokogiri_wrap_xml_node(Qnil, sibling) ;
636
+ return noko_xml_node_wrap(Qnil, sibling) ;
458
637
  }
459
638
 
460
639
  /*
@@ -463,15 +642,16 @@ static VALUE next_sibling(VALUE self)
463
642
  *
464
643
  * Returns the previous sibling node
465
644
  */
466
- static VALUE previous_sibling(VALUE self)
645
+ static VALUE
646
+ previous_sibling(VALUE self)
467
647
  {
468
648
  xmlNodePtr node, sibling;
469
649
  Data_Get_Struct(self, xmlNode, node);
470
650
 
471
651
  sibling = node->prev;
472
- if(!sibling) return Qnil;
652
+ if (!sibling) { return Qnil; }
473
653
 
474
- return Nokogiri_wrap_xml_node(Qnil, sibling);
654
+ return noko_xml_node_wrap(Qnil, sibling);
475
655
  }
476
656
 
477
657
  /*
@@ -480,15 +660,16 @@ static VALUE previous_sibling(VALUE self)
480
660
  *
481
661
  * Returns the next Nokogiri::XML::Element type sibling node.
482
662
  */
483
- static VALUE next_element(VALUE self)
663
+ static VALUE
664
+ next_element(VALUE self)
484
665
  {
485
666
  xmlNodePtr node, sibling;
486
667
  Data_Get_Struct(self, xmlNode, node);
487
668
 
488
669
  sibling = xmlNextElementSibling(node);
489
- if(!sibling) return Qnil;
670
+ if (!sibling) { return Qnil; }
490
671
 
491
- return Nokogiri_wrap_xml_node(Qnil, sibling);
672
+ return noko_xml_node_wrap(Qnil, sibling);
492
673
  }
493
674
 
494
675
  /*
@@ -497,7 +678,8 @@ static VALUE next_element(VALUE self)
497
678
  *
498
679
  * Returns the previous Nokogiri::XML::Element type sibling node.
499
680
  */
500
- static VALUE previous_element(VALUE self)
681
+ static VALUE
682
+ previous_element(VALUE self)
501
683
  {
502
684
  xmlNodePtr node, sibling;
503
685
  Data_Get_Struct(self, xmlNode, node);
@@ -506,24 +688,26 @@ static VALUE previous_element(VALUE self)
506
688
  * note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
507
689
  */
508
690
  sibling = node->prev;
509
- if(!sibling) return Qnil;
691
+ if (!sibling) { return Qnil; }
510
692
 
511
- while(sibling && sibling->type != XML_ELEMENT_NODE)
693
+ while (sibling && sibling->type != XML_ELEMENT_NODE) {
512
694
  sibling = sibling->prev;
695
+ }
513
696
 
514
- return sibling ? Nokogiri_wrap_xml_node(Qnil, sibling) : Qnil ;
697
+ return sibling ? noko_xml_node_wrap(Qnil, sibling) : Qnil ;
515
698
  }
516
699
 
517
700
  /* :nodoc: */
518
- static VALUE replace(VALUE self, VALUE new_node)
701
+ static VALUE
702
+ replace(VALUE self, VALUE new_node)
519
703
  {
520
- VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
704
+ VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
521
705
 
522
- xmlNodePtr pivot;
523
- Data_Get_Struct(self, xmlNode, pivot);
524
- nokogiri_root_node(pivot);
706
+ xmlNodePtr pivot;
707
+ Data_Get_Struct(self, xmlNode, pivot);
708
+ noko_xml_document_pin_node(pivot);
525
709
 
526
- return reparent;
710
+ return reparent;
527
711
  }
528
712
 
529
713
  /*
@@ -532,7 +716,8 @@ static VALUE replace(VALUE self, VALUE new_node)
532
716
  *
533
717
  * Get the list of children for this node as a NodeSet
534
718
  */
535
- static VALUE children(VALUE self)
719
+ static VALUE
720
+ children(VALUE self)
536
721
  {
537
722
  xmlNodePtr node;
538
723
  xmlNodePtr child;
@@ -547,15 +732,15 @@ static VALUE children(VALUE self)
547
732
 
548
733
  document = DOC_RUBY_OBJECT(node->doc);
549
734
 
550
- if(!child) return Nokogiri_wrap_xml_node_set(set, document);
735
+ if (!child) { return noko_xml_node_set_wrap(set, document); }
551
736
 
552
737
  child = child->next;
553
- while(NULL != child) {
738
+ while (NULL != child) {
554
739
  xmlXPathNodeSetAddUnique(set, child);
555
740
  child = child->next;
556
741
  }
557
742
 
558
- node_set = Nokogiri_wrap_xml_node_set(set, document);
743
+ node_set = noko_xml_node_set_wrap(set, document);
559
744
 
560
745
  return node_set;
561
746
  }
@@ -571,7 +756,8 @@ static VALUE children(VALUE self)
571
756
  *
572
757
  * @doc.root.element_children.all? { |x| x.element? } # => true
573
758
  */
574
- static VALUE element_children(VALUE self)
759
+ static VALUE
760
+ element_children(VALUE self)
575
761
  {
576
762
  xmlNodePtr node;
577
763
  xmlNodePtr child;
@@ -586,15 +772,15 @@ static VALUE element_children(VALUE self)
586
772
 
587
773
  document = DOC_RUBY_OBJECT(node->doc);
588
774
 
589
- if(!child) return Nokogiri_wrap_xml_node_set(set, document);
775
+ if (!child) { return noko_xml_node_set_wrap(set, document); }
590
776
 
591
777
  child = xmlNextElementSibling(child);
592
- while(NULL != child) {
778
+ while (NULL != child) {
593
779
  xmlXPathNodeSetAddUnique(set, child);
594
780
  child = xmlNextElementSibling(child);
595
781
  }
596
782
 
597
- node_set = Nokogiri_wrap_xml_node_set(set, document);
783
+ node_set = noko_xml_node_set_wrap(set, document);
598
784
 
599
785
  return node_set;
600
786
  }
@@ -605,15 +791,16 @@ static VALUE element_children(VALUE self)
605
791
  *
606
792
  * Returns the child node
607
793
  */
608
- static VALUE child(VALUE self)
794
+ static VALUE
795
+ child(VALUE self)
609
796
  {
610
797
  xmlNodePtr node, child;
611
798
  Data_Get_Struct(self, xmlNode, node);
612
799
 
613
800
  child = node->children;
614
- if(!child) return Qnil;
801
+ if (!child) { return Qnil; }
615
802
 
616
- return Nokogiri_wrap_xml_node(Qnil, child);
803
+ return noko_xml_node_wrap(Qnil, child);
617
804
  }
618
805
 
619
806
  /*
@@ -626,15 +813,16 @@ static VALUE child(VALUE self)
626
813
  *
627
814
  * @doc.root.first_element_child.element? # => true
628
815
  */
629
- static VALUE first_element_child(VALUE self)
816
+ static VALUE
817
+ first_element_child(VALUE self)
630
818
  {
631
819
  xmlNodePtr node, child;
632
820
  Data_Get_Struct(self, xmlNode, node);
633
821
 
634
822
  child = xmlFirstElementChild(node);
635
- if(!child) return Qnil;
823
+ if (!child) { return Qnil; }
636
824
 
637
- return Nokogiri_wrap_xml_node(Qnil, child);
825
+ return noko_xml_node_wrap(Qnil, child);
638
826
  }
639
827
 
640
828
  /*
@@ -647,15 +835,16 @@ static VALUE first_element_child(VALUE self)
647
835
  *
648
836
  * @doc.root.last_element_child.element? # => true
649
837
  */
650
- static VALUE last_element_child(VALUE self)
838
+ static VALUE
839
+ last_element_child(VALUE self)
651
840
  {
652
841
  xmlNodePtr node, child;
653
842
  Data_Get_Struct(self, xmlNode, node);
654
843
 
655
844
  child = xmlLastElementChild(node);
656
- if(!child) return Qnil;
845
+ if (!child) { return Qnil; }
657
846
 
658
- return Nokogiri_wrap_xml_node(Qnil, child);
847
+ return noko_xml_node_wrap(Qnil, child);
659
848
  }
660
849
 
661
850
  /*
@@ -664,12 +853,14 @@ static VALUE last_element_child(VALUE self)
664
853
  *
665
854
  * Returns true if +attribute+ is set
666
855
  */
667
- static VALUE key_eh(VALUE self, VALUE attribute)
856
+ static VALUE
857
+ key_eh(VALUE self, VALUE attribute)
668
858
  {
669
859
  xmlNodePtr node;
670
860
  Data_Get_Struct(self, xmlNode, node);
671
- if(xmlHasProp(node, (xmlChar *)StringValuePtr(attribute)))
861
+ if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
672
862
  return Qtrue;
863
+ }
673
864
  return Qfalse;
674
865
  }
675
866
 
@@ -679,13 +870,15 @@ static VALUE key_eh(VALUE self, VALUE attribute)
679
870
  *
680
871
  * Returns true if +attribute+ is set with +namespace+
681
872
  */
682
- static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
873
+ static VALUE
874
+ namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
683
875
  {
684
876
  xmlNodePtr node;
685
877
  Data_Get_Struct(self, xmlNode, node);
686
- if(xmlHasNsProp(node, (xmlChar *)StringValuePtr(attribute),
687
- NIL_P(namespace) ? NULL : (xmlChar *)StringValuePtr(namespace)))
878
+ if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
879
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
688
880
  return Qtrue;
881
+ }
689
882
  return Qfalse;
690
883
  }
691
884
 
@@ -695,7 +888,8 @@ static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
695
888
  *
696
889
  * Set the +property+ to +value+
697
890
  */
698
- static VALUE set(VALUE self, VALUE property, VALUE value)
891
+ static VALUE
892
+ set(VALUE self, VALUE property, VALUE value)
699
893
  {
700
894
  xmlNodePtr node, cur;
701
895
  xmlAttrPtr prop;
@@ -707,20 +901,21 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
707
901
  *
708
902
  * We can avoid this by unlinking these nodes first.
709
903
  */
710
- if (node->type != XML_ELEMENT_NODE)
711
- return(Qnil);
712
- prop = xmlHasProp(node, (xmlChar *)StringValuePtr(property));
904
+ if (node->type != XML_ELEMENT_NODE) {
905
+ return (Qnil);
906
+ }
907
+ prop = xmlHasProp(node, (xmlChar *)StringValueCStr(property));
713
908
  if (prop && prop->children) {
714
909
  for (cur = prop->children; cur; cur = cur->next) {
715
910
  if (cur->_private) {
716
- nokogiri_root_node(cur);
911
+ noko_xml_document_pin_node(cur);
717
912
  xmlUnlinkNode(cur);
718
913
  }
719
914
  }
720
915
  }
721
916
 
722
- xmlSetProp(node, (xmlChar *)StringValuePtr(property),
723
- (xmlChar *)StringValuePtr(value));
917
+ xmlSetProp(node, (xmlChar *)StringValueCStr(property),
918
+ (xmlChar *)StringValueCStr(value));
724
919
 
725
920
  return value;
726
921
  }
@@ -731,40 +926,44 @@ static VALUE set(VALUE self, VALUE property, VALUE value)
731
926
  *
732
927
  * Get the value for +attribute+
733
928
  */
734
- static VALUE get(VALUE self, VALUE rattribute)
929
+ static VALUE
930
+ get(VALUE self, VALUE rattribute)
735
931
  {
736
932
  xmlNodePtr node;
737
- xmlChar* value = 0;
738
- VALUE rvalue ;
739
- char* attribute = 0;
740
- char *colon = 0, *attr_name = 0, *prefix = 0;
933
+ xmlChar *value = 0;
934
+ VALUE rvalue;
935
+ xmlChar *colon;
936
+ xmlChar *attribute, *attr_name, *prefix;
741
937
  xmlNsPtr ns;
742
938
 
743
- if (NIL_P(rattribute)) return Qnil;
939
+ if (NIL_P(rattribute)) { return Qnil; }
744
940
 
745
941
  Data_Get_Struct(self, xmlNode, node);
746
- attribute = strdup(StringValuePtr(rattribute));
942
+ attribute = xmlCharStrdup(StringValueCStr(rattribute));
747
943
 
748
- colon = strchr(attribute, ':');
944
+ colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
749
945
  if (colon) {
750
- (*colon) = 0 ; /* create two null-terminated strings of the prefix and attribute name */
751
- prefix = attribute ;
752
- attr_name = colon + 1 ;
753
- ns = xmlSearchNs(node->doc, node, (const xmlChar *)(prefix));
946
+ /* split the attribute string into separate prefix and name by
947
+ * null-terminating the prefix at the colon */
948
+ prefix = attribute;
949
+ attr_name = colon + 1;
950
+ (*colon) = 0;
951
+
952
+ ns = xmlSearchNs(node->doc, node, prefix);
754
953
  if (ns) {
755
- value = xmlGetNsProp(node, (xmlChar*)(attr_name), ns->href);
954
+ value = xmlGetNsProp(node, attr_name, ns->href);
756
955
  } else {
757
- value = xmlGetProp(node, (xmlChar*)StringValuePtr(rattribute));
956
+ value = xmlGetProp(node, (xmlChar *)StringValueCStr(rattribute));
758
957
  }
759
958
  } else {
760
- value = xmlGetNoNsProp(node, (xmlChar*)attribute);
959
+ value = xmlGetNoNsProp(node, attribute);
761
960
  }
762
961
 
763
- free(attribute);
764
- if (!value) return Qnil;
962
+ xmlFree((void *)attribute);
963
+ if (!value) { return Qnil; }
765
964
 
766
965
  rvalue = NOKOGIRI_STR_NEW2(value);
767
- xmlFree(value);
966
+ xmlFree((void *)value);
768
967
 
769
968
  return rvalue ;
770
969
  }
@@ -775,15 +974,17 @@ static VALUE get(VALUE self, VALUE rattribute)
775
974
  *
776
975
  * Set the namespace to +namespace+
777
976
  */
778
- static VALUE set_namespace(VALUE self, VALUE namespace)
977
+ static VALUE
978
+ set_namespace(VALUE self, VALUE namespace)
779
979
  {
780
980
  xmlNodePtr node;
781
981
  xmlNsPtr ns = NULL;
782
982
 
783
983
  Data_Get_Struct(self, xmlNode, node);
784
984
 
785
- if(!NIL_P(namespace))
985
+ if (!NIL_P(namespace)) {
786
986
  Data_Get_Struct(namespace, xmlNs, ns);
987
+ }
787
988
 
788
989
  xmlSetNs(node, ns);
789
990
 
@@ -796,15 +997,16 @@ static VALUE set_namespace(VALUE self, VALUE namespace)
796
997
  *
797
998
  * Get the attribute node with +name+
798
999
  */
799
- static VALUE attr(VALUE self, VALUE name)
1000
+ static VALUE
1001
+ attr(VALUE self, VALUE name)
800
1002
  {
801
1003
  xmlNodePtr node;
802
1004
  xmlAttrPtr prop;
803
1005
  Data_Get_Struct(self, xmlNode, node);
804
- prop = xmlHasProp(node, (xmlChar *)StringValuePtr(name));
1006
+ prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
805
1007
 
806
- if(! prop) return Qnil;
807
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
1008
+ if (! prop) { return Qnil; }
1009
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
808
1010
  }
809
1011
 
810
1012
  /*
@@ -813,36 +1015,32 @@ static VALUE attr(VALUE self, VALUE name)
813
1015
  *
814
1016
  * Get the attribute node with +name+ and +namespace+
815
1017
  */
816
- static VALUE attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
1018
+ static VALUE
1019
+ attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
817
1020
  {
818
1021
  xmlNodePtr node;
819
1022
  xmlAttrPtr prop;
820
1023
  Data_Get_Struct(self, xmlNode, node);
821
- prop = xmlHasNsProp(node, (xmlChar *)StringValuePtr(name),
822
- NIL_P(namespace) ? NULL : (xmlChar *)StringValuePtr(namespace));
1024
+ prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
1025
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
823
1026
 
824
- if(! prop) return Qnil;
825
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
1027
+ if (! prop) { return Qnil; }
1028
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
826
1029
  }
827
1030
 
828
1031
  /*
829
- * call-seq:
830
- * attribute_nodes()
831
- *
832
- * returns a list containing the Node attributes.
1032
+ * @overload attribute_nodes()
1033
+ * Get the attributes for a Node
1034
+ * @return [Array<Nokogiri::XML::Attr>] containing the Node's attributes.
833
1035
  */
834
- static VALUE attribute_nodes(VALUE self)
1036
+ static VALUE
1037
+ attribute_nodes(VALUE rb_node)
835
1038
  {
836
- /* this code in the mode of xmlHasProp() */
837
- xmlNodePtr node;
838
- VALUE attr;
1039
+ xmlNodePtr c_node;
839
1040
 
840
- Data_Get_Struct(self, xmlNode, node);
1041
+ Data_Get_Struct(rb_node, xmlNode, c_node);
841
1042
 
842
- attr = rb_ary_new();
843
- Nokogiri_xml_node_properties(node, attr);
844
-
845
- return attr ;
1043
+ return noko_xml_node_attrs(c_node);
846
1044
  }
847
1045
 
848
1046
 
@@ -850,16 +1048,18 @@ static VALUE attribute_nodes(VALUE self)
850
1048
  * call-seq:
851
1049
  * namespace()
852
1050
  *
853
- * returns the default namespace set on this node (as with an "xmlns="
854
- * attribute), as a Namespace object.
1051
+ * returns the namespace of the element or attribute node as a Namespace
1052
+ * object, or nil if there is no namespace for the element or attribute.
855
1053
  */
856
- static VALUE namespace(VALUE self)
1054
+ static VALUE
1055
+ noko_xml_node_namespace(VALUE rb_node)
857
1056
  {
858
- xmlNodePtr node ;
859
- Data_Get_Struct(self, xmlNode, node);
1057
+ xmlNodePtr c_node ;
1058
+ Data_Get_Struct(rb_node, xmlNode, c_node);
860
1059
 
861
- if (node->ns)
862
- return Nokogiri_wrap_xml_namespace(node->doc, node->ns);
1060
+ if (c_node->ns) {
1061
+ return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
1062
+ }
863
1063
 
864
1064
  return Qnil ;
865
1065
  }
@@ -870,27 +1070,27 @@ static VALUE namespace(VALUE self)
870
1070
  *
871
1071
  * 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=").
872
1072
  */
873
- static VALUE namespace_definitions(VALUE self)
1073
+ static VALUE
1074
+ namespace_definitions(VALUE rb_node)
874
1075
  {
875
1076
  /* this code in the mode of xmlHasProp() */
876
- xmlNodePtr node ;
877
- VALUE list;
878
- xmlNsPtr ns;
879
-
880
- Data_Get_Struct(self, xmlNode, node);
1077
+ xmlNodePtr c_node ;
1078
+ xmlNsPtr c_namespace;
1079
+ VALUE definitions = rb_ary_new();
881
1080
 
882
- list = rb_ary_new();
1081
+ Data_Get_Struct(rb_node, xmlNode, c_node);
883
1082
 
884
- ns = node->nsDef;
885
-
886
- if(!ns) return list;
1083
+ c_namespace = c_node->nsDef;
1084
+ if (!c_namespace) {
1085
+ return definitions;
1086
+ }
887
1087
 
888
- while(NULL != ns) {
889
- rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns));
890
- ns = ns->next;
1088
+ while (c_namespace != NULL) {
1089
+ rb_ary_push(definitions, noko_xml_namespace_wrap(c_namespace, c_node->doc));
1090
+ c_namespace = c_namespace->next;
891
1091
  }
892
1092
 
893
- return list;
1093
+ return definitions;
894
1094
  }
895
1095
 
896
1096
  /*
@@ -902,26 +1102,27 @@ static VALUE namespace_definitions(VALUE self)
902
1102
  * namespaces ("xmlns=" style) for self are included in this array; Default
903
1103
  * namespaces for ancestors, however, are not. See also #namespaces
904
1104
  */
905
- static VALUE namespace_scopes(VALUE self)
1105
+ static VALUE
1106
+ namespace_scopes(VALUE rb_node)
906
1107
  {
907
- xmlNodePtr node ;
908
- VALUE list;
909
- xmlNsPtr *ns_list;
1108
+ xmlNodePtr c_node ;
1109
+ xmlNsPtr *namespaces;
1110
+ VALUE scopes = rb_ary_new();
910
1111
  int j;
911
1112
 
912
- Data_Get_Struct(self, xmlNode, node);
913
-
914
- list = rb_ary_new();
915
- ns_list = xmlGetNsList(node->doc, node);
1113
+ Data_Get_Struct(rb_node, xmlNode, c_node);
916
1114
 
917
- if(!ns_list) return list;
1115
+ namespaces = xmlGetNsList(c_node->doc, c_node);
1116
+ if (!namespaces) {
1117
+ return scopes;
1118
+ }
918
1119
 
919
- for (j = 0 ; ns_list[j] != NULL ; ++j) {
920
- rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns_list[j]));
1120
+ for (j = 0 ; namespaces[j] != NULL ; ++j) {
1121
+ rb_ary_push(scopes, noko_xml_namespace_wrap(namespaces[j], c_node->doc));
921
1122
  }
922
1123
 
923
- xmlFree(ns_list);
924
- return list;
1124
+ xmlFree(namespaces);
1125
+ return scopes;
925
1126
  }
926
1127
 
927
1128
  /*
@@ -930,7 +1131,8 @@ static VALUE namespace_scopes(VALUE self)
930
1131
  *
931
1132
  * Get the type for this Node
932
1133
  */
933
- static VALUE node_type(VALUE self)
1134
+ static VALUE
1135
+ node_type(VALUE self)
934
1136
  {
935
1137
  xmlNodePtr node;
936
1138
  Data_Get_Struct(self, xmlNode, node);
@@ -943,7 +1145,8 @@ static VALUE node_type(VALUE self)
943
1145
  *
944
1146
  * Set the content for this Node
945
1147
  */
946
- static VALUE native_content(VALUE self, VALUE content)
1148
+ static VALUE
1149
+ set_native_content(VALUE self, VALUE content)
947
1150
  {
948
1151
  xmlNodePtr node, child, next ;
949
1152
  Data_Get_Struct(self, xmlNode, node);
@@ -952,11 +1155,11 @@ static VALUE native_content(VALUE self, VALUE content)
952
1155
  while (NULL != child) {
953
1156
  next = child->next ;
954
1157
  xmlUnlinkNode(child) ;
955
- nokogiri_root_node(child);
1158
+ noko_xml_document_pin_node(child);
956
1159
  child = next ;
957
1160
  }
958
1161
 
959
- xmlNodeSetContent(node, (xmlChar *)StringValuePtr(content));
1162
+ xmlNodeSetContent(node, (xmlChar *)StringValueCStr(content));
960
1163
  return content;
961
1164
  }
962
1165
 
@@ -964,17 +1167,19 @@ static VALUE native_content(VALUE self, VALUE content)
964
1167
  * call-seq:
965
1168
  * content
966
1169
  *
967
- * Returns the content for this Node
1170
+ * Returns the plaintext content for this Node. Note that entities will always
1171
+ * be expanded in the returned string.
968
1172
  */
969
- static VALUE get_content(VALUE self)
1173
+ static VALUE
1174
+ get_native_content(VALUE self)
970
1175
  {
971
1176
  xmlNodePtr node;
972
- xmlChar * content;
1177
+ xmlChar *content;
973
1178
 
974
1179
  Data_Get_Struct(self, xmlNode, node);
975
1180
 
976
1181
  content = xmlNodeGetContent(node);
977
- if(content) {
1182
+ if (content) {
978
1183
  VALUE rval = NOKOGIRI_STR_NEW2(content);
979
1184
  xmlFree(content);
980
1185
  return rval;
@@ -982,8 +1187,55 @@ static VALUE get_content(VALUE self)
982
1187
  return Qnil;
983
1188
  }
984
1189
 
1190
+ /*
1191
+ * call-seq:
1192
+ * lang=
1193
+ *
1194
+ * Set the language of a node, i.e. the values of the xml:lang attribute.
1195
+ */
1196
+ static VALUE
1197
+ set_lang(VALUE self_rb, VALUE lang_rb)
1198
+ {
1199
+ xmlNodePtr self ;
1200
+ xmlChar *lang ;
1201
+
1202
+ Data_Get_Struct(self_rb, xmlNode, self);
1203
+ lang = (xmlChar *)StringValueCStr(lang_rb);
1204
+
1205
+ xmlNodeSetLang(self, lang);
1206
+
1207
+ return Qnil ;
1208
+ }
1209
+
1210
+ /*
1211
+ * call-seq:
1212
+ * lang
1213
+ *
1214
+ * Searches the language of a node, i.e. the values of the xml:lang attribute or
1215
+ * the one carried by the nearest ancestor.
1216
+ */
1217
+ static VALUE
1218
+ get_lang(VALUE self_rb)
1219
+ {
1220
+ xmlNodePtr self ;
1221
+ xmlChar *lang ;
1222
+ VALUE lang_rb ;
1223
+
1224
+ Data_Get_Struct(self_rb, xmlNode, self);
1225
+
1226
+ lang = xmlNodeGetLang(self);
1227
+ if (lang) {
1228
+ lang_rb = NOKOGIRI_STR_NEW2(lang);
1229
+ xmlFree(lang);
1230
+ return lang_rb ;
1231
+ }
1232
+
1233
+ return Qnil ;
1234
+ }
1235
+
985
1236
  /* :nodoc: */
986
- static VALUE add_child(VALUE self, VALUE new_child)
1237
+ static VALUE
1238
+ add_child(VALUE self, VALUE new_child)
987
1239
  {
988
1240
  return reparent_node_with(self, new_child, xmlAddChild);
989
1241
  }
@@ -994,15 +1246,16 @@ static VALUE add_child(VALUE self, VALUE new_child)
994
1246
  *
995
1247
  * Get the parent Node for this Node
996
1248
  */
997
- static VALUE get_parent(VALUE self)
1249
+ static VALUE
1250
+ get_parent(VALUE self)
998
1251
  {
999
1252
  xmlNodePtr node, parent;
1000
1253
  Data_Get_Struct(self, xmlNode, node);
1001
1254
 
1002
1255
  parent = node->parent;
1003
- if(!parent) return Qnil;
1256
+ if (!parent) { return Qnil; }
1004
1257
 
1005
- return Nokogiri_wrap_xml_node(Qnil, parent) ;
1258
+ return noko_xml_node_wrap(Qnil, parent) ;
1006
1259
  }
1007
1260
 
1008
1261
  /*
@@ -1011,11 +1264,12 @@ static VALUE get_parent(VALUE self)
1011
1264
  *
1012
1265
  * Set the name for this Node
1013
1266
  */
1014
- static VALUE set_name(VALUE self, VALUE new_name)
1267
+ static VALUE
1268
+ set_name(VALUE self, VALUE new_name)
1015
1269
  {
1016
1270
  xmlNodePtr node;
1017
1271
  Data_Get_Struct(self, xmlNode, node);
1018
- xmlNodeSetName(node, (xmlChar*)StringValuePtr(new_name));
1272
+ xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
1019
1273
  return new_name;
1020
1274
  }
1021
1275
 
@@ -1025,12 +1279,14 @@ static VALUE set_name(VALUE self, VALUE new_name)
1025
1279
  *
1026
1280
  * Returns the name for this Node
1027
1281
  */
1028
- static VALUE get_name(VALUE self)
1282
+ static VALUE
1283
+ get_name(VALUE self)
1029
1284
  {
1030
1285
  xmlNodePtr node;
1031
1286
  Data_Get_Struct(self, xmlNode, node);
1032
- if(node->name)
1287
+ if (node->name) {
1033
1288
  return NOKOGIRI_STR_NEW2(node->name);
1289
+ }
1034
1290
  return Qnil;
1035
1291
  }
1036
1292
 
@@ -1040,28 +1296,39 @@ static VALUE get_name(VALUE self)
1040
1296
  *
1041
1297
  * Returns the path associated with this Node
1042
1298
  */
1043
- static VALUE path(VALUE self)
1299
+ static VALUE
1300
+ noko_xml_node_path(VALUE rb_node)
1044
1301
  {
1045
- xmlNodePtr node;
1046
- xmlChar *path ;
1302
+ xmlNodePtr c_node;
1303
+ xmlChar *c_path ;
1047
1304
  VALUE rval;
1048
1305
 
1049
- Data_Get_Struct(self, xmlNode, node);
1306
+ Data_Get_Struct(rb_node, xmlNode, c_node);
1307
+
1308
+ c_path = xmlGetNodePath(c_node);
1309
+ if (c_path == NULL) {
1310
+ // see https://github.com/sparklemotion/nokogiri/issues/2250
1311
+ // this behavior is clearly undesirable, but is what libxml <= 2.9.10 returned, and so we
1312
+ // do this for now to preserve the behavior across libxml2 versions.
1313
+ rval = NOKOGIRI_STR_NEW2("?");
1314
+ } else {
1315
+ rval = NOKOGIRI_STR_NEW2(c_path);
1316
+ xmlFree(c_path);
1317
+ }
1050
1318
 
1051
- path = xmlGetNodePath(node);
1052
- rval = NOKOGIRI_STR_NEW2(path);
1053
- xmlFree(path);
1054
1319
  return rval ;
1055
1320
  }
1056
1321
 
1057
1322
  /* :nodoc: */
1058
- static VALUE add_next_sibling(VALUE self, VALUE new_sibling)
1323
+ static VALUE
1324
+ add_next_sibling(VALUE self, VALUE new_sibling)
1059
1325
  {
1060
1326
  return reparent_node_with(self, new_sibling, xmlAddNextSibling) ;
1061
1327
  }
1062
1328
 
1063
1329
  /* :nodoc: */
1064
- static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
1330
+ static VALUE
1331
+ add_previous_sibling(VALUE self, VALUE new_sibling)
1065
1332
  {
1066
1333
  return reparent_node_with(self, new_sibling, xmlAddPrevSibling) ;
1067
1334
  }
@@ -1072,15 +1339,17 @@ static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
1072
1339
  *
1073
1340
  * Write this Node to +io+ with +encoding+ and +options+
1074
1341
  */
1075
- static VALUE native_write_to(
1076
- VALUE self,
1077
- VALUE io,
1078
- VALUE encoding,
1079
- VALUE indent_string,
1080
- VALUE options
1081
- ) {
1342
+ static VALUE
1343
+ native_write_to(
1344
+ VALUE self,
1345
+ VALUE io,
1346
+ VALUE encoding,
1347
+ VALUE indent_string,
1348
+ VALUE options
1349
+ )
1350
+ {
1082
1351
  xmlNodePtr node;
1083
- const char * before_indent;
1352
+ const char *before_indent;
1084
1353
  xmlSaveCtxtPtr savectx;
1085
1354
 
1086
1355
  Data_Get_Struct(self, xmlNode, node);
@@ -1089,15 +1358,15 @@ static VALUE native_write_to(
1089
1358
 
1090
1359
  before_indent = xmlTreeIndentString;
1091
1360
 
1092
- xmlTreeIndentString = StringValuePtr(indent_string);
1361
+ xmlTreeIndentString = StringValueCStr(indent_string);
1093
1362
 
1094
1363
  savectx = xmlSaveToIO(
1095
- (xmlOutputWriteCallback)io_write_callback,
1096
- (xmlOutputCloseCallback)io_close_callback,
1097
- (void *)io,
1098
- RTEST(encoding) ? StringValuePtr(encoding) : NULL,
1099
- (int)NUM2INT(options)
1100
- );
1364
+ (xmlOutputWriteCallback)noko_io_write,
1365
+ (xmlOutputCloseCallback)noko_io_close,
1366
+ (void *)io,
1367
+ RTEST(encoding) ? StringValueCStr(encoding) : NULL,
1368
+ (int)NUM2INT(options)
1369
+ );
1101
1370
 
1102
1371
  xmlSaveTree(savectx, node);
1103
1372
  xmlSaveClose(savectx);
@@ -1112,7 +1381,8 @@ static VALUE native_write_to(
1112
1381
  *
1113
1382
  * Returns the line for this Node
1114
1383
  */
1115
- static VALUE line(VALUE self)
1384
+ static VALUE
1385
+ line(VALUE self)
1116
1386
  {
1117
1387
  xmlNodePtr node;
1118
1388
  Data_Get_Struct(self, xmlNode, node);
@@ -1120,6 +1390,26 @@ static VALUE line(VALUE self)
1120
1390
  return INT2NUM(xmlGetLineNo(node));
1121
1391
  }
1122
1392
 
1393
+ /*
1394
+ * call-seq:
1395
+ * line=(num)
1396
+ *
1397
+ * Sets the line for this Node. num must be less than 65535.
1398
+ */
1399
+ static VALUE
1400
+ set_line(VALUE self, VALUE num)
1401
+ {
1402
+ xmlNodePtr node;
1403
+ int value = NUM2INT(num);
1404
+
1405
+ Data_Get_Struct(self, xmlNode, node);
1406
+ if (value < 65535) {
1407
+ node->line = value;
1408
+ }
1409
+
1410
+ return num;
1411
+ }
1412
+
1123
1413
  /*
1124
1414
  * call-seq:
1125
1415
  * add_namespace_definition(prefix, href)
@@ -1131,45 +1421,47 @@ static VALUE line(VALUE self)
1131
1421
  * show up in #attributes, but they will be included as an xmlns attribute
1132
1422
  * when the node is serialized to XML.
1133
1423
  */
1134
- static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
1424
+ static VALUE
1425
+ add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
1135
1426
  {
1136
- xmlNodePtr node, namespacee;
1137
- xmlNsPtr ns;
1427
+ xmlNodePtr c_node, element;
1428
+ xmlNsPtr c_namespace;
1429
+ const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
1138
1430
 
1139
- Data_Get_Struct(self, xmlNode, node);
1140
- namespacee = node ;
1431
+ Data_Get_Struct(rb_node, xmlNode, c_node);
1432
+ element = c_node ;
1141
1433
 
1142
- ns = xmlSearchNs(
1143
- node->doc,
1144
- node,
1145
- (const xmlChar *)(NIL_P(prefix) ? NULL : StringValuePtr(prefix))
1146
- );
1434
+ c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
1147
1435
 
1148
- if(!ns) {
1149
- if (node->type != XML_ELEMENT_NODE) {
1150
- namespacee = node->parent;
1436
+ if (!c_namespace) {
1437
+ if (c_node->type != XML_ELEMENT_NODE) {
1438
+ element = c_node->parent;
1151
1439
  }
1152
- ns = xmlNewNs(
1153
- namespacee,
1154
- (const xmlChar *)StringValuePtr(href),
1155
- (const xmlChar *)(NIL_P(prefix) ? NULL : StringValuePtr(prefix))
1156
- );
1440
+ c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
1157
1441
  }
1158
1442
 
1159
- if (!ns) return Qnil ;
1443
+ if (!c_namespace) {
1444
+ return Qnil ;
1445
+ }
1160
1446
 
1161
- if(NIL_P(prefix) || node != namespacee) xmlSetNs(node, ns);
1447
+ if (NIL_P(rb_prefix) || c_node != element) {
1448
+ xmlSetNs(c_node, c_namespace);
1449
+ }
1162
1450
 
1163
- return Nokogiri_wrap_xml_namespace(node->doc, ns);
1451
+ return noko_xml_namespace_wrap(c_namespace, c_node->doc);
1164
1452
  }
1165
1453
 
1166
1454
  /*
1167
- * call-seq:
1168
- * new(name, document)
1169
- *
1170
- * Create a new node with +name+ sharing GC lifecycle with +document+
1455
+ * @overload new(name, document)
1456
+ * Create a new node with +name+ sharing GC lifecycle with +document+.
1457
+ * @param name [String]
1458
+ * @param document [Nokogiri::XML::Document]
1459
+ * @yieldparam node [Nokogiri::XML::Node]
1460
+ * @return [Nokogiri::XML::Node]
1461
+ * @see Nokogiri::XML::Node#initialize
1171
1462
  */
1172
- static VALUE new(int argc, VALUE *argv, VALUE klass)
1463
+ static VALUE
1464
+ rb_xml_node_new(int argc, VALUE *argv, VALUE klass)
1173
1465
  {
1174
1466
  xmlDocPtr doc;
1175
1467
  xmlNodePtr node;
@@ -1182,17 +1474,17 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
1182
1474
 
1183
1475
  Data_Get_Struct(document, xmlDoc, doc);
1184
1476
 
1185
- node = xmlNewNode(NULL, (xmlChar *)StringValuePtr(name));
1477
+ node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(name));
1186
1478
  node->doc = doc->doc;
1187
- nokogiri_root_node(node);
1479
+ noko_xml_document_pin_node(node);
1188
1480
 
1189
- rb_node = Nokogiri_wrap_xml_node(
1190
- klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1191
- node
1192
- );
1481
+ rb_node = noko_xml_node_wrap(
1482
+ klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1483
+ node
1484
+ );
1193
1485
  rb_obj_call_init(rb_node, argc, argv);
1194
1486
 
1195
- if(rb_block_given_p()) rb_yield(rb_node);
1487
+ if (rb_block_given_p()) { rb_yield(rb_node); }
1196
1488
 
1197
1489
  return rb_node;
1198
1490
  }
@@ -1203,7 +1495,8 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
1203
1495
  *
1204
1496
  * Returns the Node as html.
1205
1497
  */
1206
- static VALUE dump_html(VALUE self)
1498
+ static VALUE
1499
+ dump_html(VALUE self)
1207
1500
  {
1208
1501
  xmlBufferPtr buf ;
1209
1502
  xmlNodePtr node ;
@@ -1224,7 +1517,8 @@ static VALUE dump_html(VALUE self)
1224
1517
  *
1225
1518
  * Compare this Node to +other+ with respect to their Document
1226
1519
  */
1227
- static VALUE compare(VALUE self, VALUE _other)
1520
+ static VALUE
1521
+ compare(VALUE self, VALUE _other)
1228
1522
  {
1229
1523
  xmlNodePtr node, other;
1230
1524
  Data_Get_Struct(self, xmlNode, node);
@@ -1241,7 +1535,8 @@ static VALUE compare(VALUE self, VALUE _other)
1241
1535
  * Loads and substitutes all xinclude elements below the node. The
1242
1536
  * parser context will be initialized with +options+.
1243
1537
  */
1244
- static VALUE process_xincludes(VALUE self, VALUE options)
1538
+ static VALUE
1539
+ process_xincludes(VALUE self, VALUE options)
1245
1540
  {
1246
1541
  int rcode ;
1247
1542
  xmlNodePtr node;
@@ -1257,10 +1552,11 @@ static VALUE process_xincludes(VALUE self, VALUE options)
1257
1552
  xmlErrorPtr error;
1258
1553
 
1259
1554
  error = xmlGetLastError();
1260
- if(error)
1261
- rb_exc_raise(Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error));
1262
- else
1555
+ if (error) {
1556
+ rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
1557
+ } else {
1263
1558
  rb_raise(rb_eRuntimeError, "Could not perform xinclude substitution");
1559
+ }
1264
1560
  }
1265
1561
 
1266
1562
  return self;
@@ -1268,267 +1564,276 @@ static VALUE process_xincludes(VALUE self, VALUE options)
1268
1564
 
1269
1565
 
1270
1566
  /* TODO: DOCUMENT ME */
1271
- static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1567
+ static VALUE
1568
+ in_context(VALUE self, VALUE _str, VALUE _options)
1272
1569
  {
1273
- xmlNodePtr node, list = 0, tmp, child_iter, node_children, doc_children;
1274
- xmlNodeSetPtr set;
1275
- xmlParserErrors error;
1276
- VALUE doc, err;
1277
- int doc_is_empty;
1570
+ xmlNodePtr node, list = 0, tmp, child_iter, node_children, doc_children;
1571
+ xmlNodeSetPtr set;
1572
+ xmlParserErrors error;
1573
+ VALUE doc, err;
1574
+ int doc_is_empty;
1278
1575
 
1279
- Data_Get_Struct(self, xmlNode, node);
1576
+ Data_Get_Struct(self, xmlNode, node);
1280
1577
 
1281
- doc = DOC_RUBY_OBJECT(node->doc);
1282
- err = rb_iv_get(doc, "@errors");
1283
- doc_is_empty = (node->doc->children == NULL) ? 1 : 0;
1284
- node_children = node->children;
1285
- doc_children = node->doc->children;
1578
+ doc = DOC_RUBY_OBJECT(node->doc);
1579
+ err = rb_iv_get(doc, "@errors");
1580
+ doc_is_empty = (node->doc->children == NULL) ? 1 : 0;
1581
+ node_children = node->children;
1582
+ doc_children = node->doc->children;
1286
1583
 
1287
- xmlSetStructuredErrorFunc((void *)err, Nokogiri_error_array_pusher);
1584
+ xmlSetStructuredErrorFunc((void *)err, Nokogiri_error_array_pusher);
1288
1585
 
1289
- /* Twiddle global variable because of a bug in libxml2.
1290
- * http://git.gnome.org/browse/libxml2/commit/?id=e20fb5a72c83cbfc8e4a8aa3943c6be8febadab7
1291
- */
1586
+ /* Twiddle global variable because of a bug in libxml2.
1587
+ * http://git.gnome.org/browse/libxml2/commit/?id=e20fb5a72c83cbfc8e4a8aa3943c6be8febadab7
1588
+ */
1292
1589
  #ifndef HTML_PARSE_NOIMPLIED
1293
- htmlHandleOmittedElem(0);
1590
+ htmlHandleOmittedElem(0);
1294
1591
  #endif
1295
1592
 
1296
- /* This function adds a fake node to the child of +node+. If the parser
1297
- * does not exit cleanly with XML_ERR_OK, the list is freed. This can
1298
- * leave the child pointers in a bad state if they were originally empty.
1299
- *
1300
- * http://git.gnome.org/browse/libxml2/tree/parser.c#n13177
1301
- * */
1302
- error = xmlParseInNodeContext(node, StringValuePtr(_str),
1303
- (int)RSTRING_LEN(_str),
1304
- (int)NUM2INT(_options), &list);
1305
-
1306
- /* xmlParseInNodeContext should not mutate the original document or node,
1307
- * so reassigning these pointers should be OK. The reason we're reassigning
1308
- * is because if there were errors, it's possible for the child pointers
1309
- * to be manipulated. */
1310
- if (error != XML_ERR_OK) {
1311
- node->doc->children = doc_children;
1312
- node->children = node_children;
1313
- }
1593
+ /* This function adds a fake node to the child of +node+. If the parser
1594
+ * does not exit cleanly with XML_ERR_OK, the list is freed. This can
1595
+ * leave the child pointers in a bad state if they were originally empty.
1596
+ *
1597
+ * http://git.gnome.org/browse/libxml2/tree/parser.c#n13177
1598
+ * */
1599
+ error = xmlParseInNodeContext(node, StringValuePtr(_str),
1600
+ (int)RSTRING_LEN(_str),
1601
+ (int)NUM2INT(_options), &list);
1602
+
1603
+ /* xmlParseInNodeContext should not mutate the original document or node,
1604
+ * so reassigning these pointers should be OK. The reason we're reassigning
1605
+ * is because if there were errors, it's possible for the child pointers
1606
+ * to be manipulated. */
1607
+ if (error != XML_ERR_OK) {
1608
+ node->doc->children = doc_children;
1609
+ node->children = node_children;
1610
+ }
1314
1611
 
1315
- /* make sure parent/child pointers are coherent so an unlink will work
1316
- * properly (#331)
1317
- */
1318
- child_iter = node->doc->children ;
1319
- while (child_iter) {
1320
- if (child_iter->parent != (xmlNodePtr)node->doc)
1321
- child_iter->parent = (xmlNodePtr)node->doc;
1322
- child_iter = child_iter->next;
1612
+ /* make sure parent/child pointers are coherent so an unlink will work
1613
+ * properly (#331)
1614
+ */
1615
+ child_iter = node->doc->children ;
1616
+ while (child_iter) {
1617
+ if (child_iter->parent != (xmlNodePtr)node->doc) {
1618
+ child_iter->parent = (xmlNodePtr)node->doc;
1323
1619
  }
1620
+ child_iter = child_iter->next;
1621
+ }
1324
1622
 
1325
1623
  #ifndef HTML_PARSE_NOIMPLIED
1326
- htmlHandleOmittedElem(1);
1624
+ htmlHandleOmittedElem(1);
1327
1625
  #endif
1328
1626
 
1329
- xmlSetStructuredErrorFunc(NULL, NULL);
1330
-
1331
- /* Workaround for a libxml2 bug where a parsing error may leave a broken
1332
- * node reference in node->doc->children.
1333
- * This workaround is limited to when a parse error occurs, the document
1334
- * went from having no children to having children, and the context node is
1335
- * part of a document fragment.
1336
- * https://bugzilla.gnome.org/show_bug.cgi?id=668155
1337
- */
1338
- if (error != XML_ERR_OK && doc_is_empty && node->doc->children != NULL) {
1339
- child_iter = node;
1340
- while (child_iter->parent)
1341
- child_iter = child_iter->parent;
1627
+ xmlSetStructuredErrorFunc(NULL, NULL);
1342
1628
 
1343
- if (child_iter->type == XML_DOCUMENT_FRAG_NODE)
1344
- node->doc->children = NULL;
1629
+ /* Workaround for a libxml2 bug where a parsing error may leave a broken
1630
+ * node reference in node->doc->children.
1631
+ * This workaround is limited to when a parse error occurs, the document
1632
+ * went from having no children to having children, and the context node is
1633
+ * part of a document fragment.
1634
+ * https://bugzilla.gnome.org/show_bug.cgi?id=668155
1635
+ */
1636
+ if (error != XML_ERR_OK && doc_is_empty && node->doc->children != NULL) {
1637
+ child_iter = node;
1638
+ while (child_iter->parent) {
1639
+ child_iter = child_iter->parent;
1345
1640
  }
1346
1641
 
1347
- /* FIXME: This probably needs to handle more constants... */
1348
- switch (error) {
1349
- case XML_ERR_INTERNAL_ERROR:
1350
- case XML_ERR_NO_MEMORY:
1351
- rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
1352
- break;
1353
- default:
1354
- break;
1642
+ if (child_iter->type == XML_DOCUMENT_FRAG_NODE) {
1643
+ node->doc->children = NULL;
1355
1644
  }
1645
+ }
1356
1646
 
1357
- set = xmlXPathNodeSetCreate(NULL);
1647
+ /* FIXME: This probably needs to handle more constants... */
1648
+ switch (error) {
1649
+ case XML_ERR_INTERNAL_ERROR:
1650
+ case XML_ERR_NO_MEMORY:
1651
+ rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
1652
+ break;
1653
+ default:
1654
+ break;
1655
+ }
1358
1656
 
1359
- while (list) {
1360
- tmp = list->next;
1361
- list->next = NULL;
1362
- xmlXPathNodeSetAddUnique(set, list);
1363
- nokogiri_root_node(list);
1364
- list = tmp;
1365
- }
1657
+ set = xmlXPathNodeSetCreate(NULL);
1366
1658
 
1367
- return Nokogiri_wrap_xml_node_set(set, doc);
1659
+ while (list) {
1660
+ tmp = list->next;
1661
+ list->next = NULL;
1662
+ xmlXPathNodeSetAddUnique(set, list);
1663
+ noko_xml_document_pin_node(list);
1664
+ list = tmp;
1665
+ }
1666
+
1667
+ return noko_xml_node_set_wrap(set, doc);
1368
1668
  }
1369
1669
 
1370
1670
 
1371
- VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node)
1671
+ VALUE
1672
+ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1372
1673
  {
1373
- VALUE document = Qnil ;
1374
- VALUE node_cache = Qnil ;
1375
- VALUE rb_node = Qnil ;
1674
+ VALUE rb_document, rb_node_cache, rb_node;
1376
1675
  nokogiriTuplePtr node_has_a_document;
1377
- xmlDocPtr doc;
1676
+ xmlDocPtr c_doc;
1378
1677
  void (*mark_method)(xmlNodePtr) = NULL ;
1379
1678
 
1380
- assert(node);
1679
+ assert(c_node);
1381
1680
 
1382
- if(node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE)
1383
- return DOC_RUBY_OBJECT(node->doc);
1681
+ if (c_node->type == XML_DOCUMENT_NODE || c_node->type == XML_HTML_DOCUMENT_NODE) {
1682
+ return DOC_RUBY_OBJECT(c_node->doc);
1683
+ }
1384
1684
 
1385
1685
  /* It's OK if the node doesn't have a fully-realized document (as in XML::Reader). */
1386
1686
  /* see https://github.com/sparklemotion/nokogiri/issues/95 */
1387
1687
  /* and https://github.com/sparklemotion/nokogiri/issues/439 */
1388
- doc = node->doc;
1389
- if (doc->type == XML_DOCUMENT_FRAG_NODE) doc = doc->doc;
1390
- node_has_a_document = DOC_RUBY_OBJECT_TEST(doc);
1688
+ c_doc = c_node->doc;
1689
+ if (c_doc->type == XML_DOCUMENT_FRAG_NODE) { c_doc = c_doc->doc; }
1690
+ node_has_a_document = DOC_RUBY_OBJECT_TEST(c_doc);
1391
1691
 
1392
- if(node->_private && node_has_a_document)
1393
- return (VALUE)node->_private;
1692
+ if (c_node->_private && node_has_a_document) {
1693
+ return (VALUE)c_node->_private;
1694
+ }
1394
1695
 
1395
- if(!RTEST(klass)) {
1396
- switch(node->type)
1397
- {
1398
- case XML_ELEMENT_NODE:
1399
- klass = cNokogiriXmlElement;
1400
- break;
1401
- case XML_TEXT_NODE:
1402
- klass = cNokogiriXmlText;
1403
- break;
1404
- case XML_ATTRIBUTE_NODE:
1405
- klass = cNokogiriXmlAttr;
1406
- break;
1407
- case XML_ENTITY_REF_NODE:
1408
- klass = cNokogiriXmlEntityReference;
1409
- break;
1410
- case XML_COMMENT_NODE:
1411
- klass = cNokogiriXmlComment;
1412
- break;
1413
- case XML_DOCUMENT_FRAG_NODE:
1414
- klass = cNokogiriXmlDocumentFragment;
1415
- break;
1416
- case XML_PI_NODE:
1417
- klass = cNokogiriXmlProcessingInstruction;
1418
- break;
1419
- case XML_ENTITY_DECL:
1420
- klass = cNokogiriXmlEntityDecl;
1421
- break;
1422
- case XML_CDATA_SECTION_NODE:
1423
- klass = cNokogiriXmlCData;
1424
- break;
1425
- case XML_DTD_NODE:
1426
- klass = cNokogiriXmlDtd;
1427
- break;
1428
- case XML_ATTRIBUTE_DECL:
1429
- klass = cNokogiriXmlAttributeDecl;
1430
- break;
1431
- case XML_ELEMENT_DECL:
1432
- klass = cNokogiriXmlElementDecl;
1433
- break;
1434
- default:
1435
- klass = cNokogiriXmlNode;
1696
+ if (!RTEST(rb_class)) {
1697
+ switch (c_node->type) {
1698
+ case XML_ELEMENT_NODE:
1699
+ rb_class = cNokogiriXmlElement;
1700
+ break;
1701
+ case XML_TEXT_NODE:
1702
+ rb_class = cNokogiriXmlText;
1703
+ break;
1704
+ case XML_ATTRIBUTE_NODE:
1705
+ rb_class = cNokogiriXmlAttr;
1706
+ break;
1707
+ case XML_ENTITY_REF_NODE:
1708
+ rb_class = cNokogiriXmlEntityReference;
1709
+ break;
1710
+ case XML_COMMENT_NODE:
1711
+ rb_class = cNokogiriXmlComment;
1712
+ break;
1713
+ case XML_DOCUMENT_FRAG_NODE:
1714
+ rb_class = cNokogiriXmlDocumentFragment;
1715
+ break;
1716
+ case XML_PI_NODE:
1717
+ rb_class = cNokogiriXmlProcessingInstruction;
1718
+ break;
1719
+ case XML_ENTITY_DECL:
1720
+ rb_class = cNokogiriXmlEntityDecl;
1721
+ break;
1722
+ case XML_CDATA_SECTION_NODE:
1723
+ rb_class = cNokogiriXmlCData;
1724
+ break;
1725
+ case XML_DTD_NODE:
1726
+ rb_class = cNokogiriXmlDtd;
1727
+ break;
1728
+ case XML_ATTRIBUTE_DECL:
1729
+ rb_class = cNokogiriXmlAttributeDecl;
1730
+ break;
1731
+ case XML_ELEMENT_DECL:
1732
+ rb_class = cNokogiriXmlElementDecl;
1733
+ break;
1734
+ default:
1735
+ rb_class = cNokogiriXmlNode;
1436
1736
  }
1437
1737
  }
1438
1738
 
1439
1739
  mark_method = node_has_a_document ? mark : NULL ;
1440
1740
 
1441
- rb_node = Data_Wrap_Struct(klass, mark_method, debug_node_dealloc, node) ;
1442
- node->_private = (void *)rb_node;
1741
+ rb_node = Data_Wrap_Struct(rb_class, mark_method, debug_node_dealloc, c_node) ;
1742
+ c_node->_private = (void *)rb_node;
1443
1743
 
1444
1744
  if (node_has_a_document) {
1445
- document = DOC_RUBY_OBJECT(doc);
1446
- node_cache = DOC_NODE_CACHE(doc);
1447
- rb_ary_push(node_cache, rb_node);
1448
- rb_funcall(document, decorate, 1, rb_node);
1745
+ rb_document = DOC_RUBY_OBJECT(c_doc);
1746
+ rb_node_cache = DOC_NODE_CACHE(c_doc);
1747
+ rb_ary_push(rb_node_cache, rb_node);
1748
+ rb_funcall(rb_document, id_decorate, 1, rb_node);
1449
1749
  }
1450
1750
 
1451
1751
  return rb_node ;
1452
1752
  }
1453
1753
 
1454
1754
 
1455
- void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_list)
1755
+ /*
1756
+ * return Array<Nokogiri::XML::Attr> containing the node's attributes
1757
+ */
1758
+ VALUE
1759
+ noko_xml_node_attrs(xmlNodePtr c_node)
1456
1760
  {
1457
- xmlAttrPtr prop;
1458
- prop = node->properties ;
1459
- while (prop != NULL) {
1460
- rb_ary_push(attr_list, Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop));
1461
- prop = prop->next ;
1761
+ VALUE rb_properties = rb_ary_new();
1762
+ xmlAttrPtr c_property;
1763
+
1764
+ c_property = c_node->properties ;
1765
+ while (c_property != NULL) {
1766
+ rb_ary_push(rb_properties, noko_xml_node_wrap(Qnil, (xmlNodePtr)c_property));
1767
+ c_property = c_property->next ;
1462
1768
  }
1463
- }
1464
1769
 
1465
- VALUE cNokogiriXmlNode ;
1466
- VALUE cNokogiriXmlElement ;
1770
+ return rb_properties;
1771
+ }
1467
1772
 
1468
- void init_xml_node()
1773
+ void
1774
+ noko_init_xml_node()
1469
1775
  {
1470
- VALUE nokogiri = rb_define_module("Nokogiri");
1471
- VALUE xml = rb_define_module_under(nokogiri, "XML");
1472
- VALUE klass = rb_define_class_under(xml, "Node", rb_cObject);
1473
-
1474
- cNokogiriXmlNode = klass;
1475
-
1476
- cNokogiriXmlElement = rb_define_class_under(xml, "Element", klass);
1477
-
1478
- rb_define_singleton_method(klass, "new", new, -1);
1479
-
1480
- rb_define_method(klass, "add_namespace_definition", add_namespace_definition, 2);
1481
- rb_define_method(klass, "node_name", get_name, 0);
1482
- rb_define_method(klass, "document", document, 0);
1483
- rb_define_method(klass, "node_name=", set_name, 1);
1484
- rb_define_method(klass, "parent", get_parent, 0);
1485
- rb_define_method(klass, "child", child, 0);
1486
- rb_define_method(klass, "first_element_child", first_element_child, 0);
1487
- rb_define_method(klass, "last_element_child", last_element_child, 0);
1488
- rb_define_method(klass, "children", children, 0);
1489
- rb_define_method(klass, "element_children", element_children, 0);
1490
- rb_define_method(klass, "next_sibling", next_sibling, 0);
1491
- rb_define_method(klass, "previous_sibling", previous_sibling, 0);
1492
- rb_define_method(klass, "next_element", next_element, 0);
1493
- rb_define_method(klass, "previous_element", previous_element, 0);
1494
- rb_define_method(klass, "node_type", node_type, 0);
1495
- rb_define_method(klass, "content", get_content, 0);
1496
- rb_define_method(klass, "path", path, 0);
1497
- rb_define_method(klass, "key?", key_eh, 1);
1498
- rb_define_method(klass, "namespaced_key?", namespaced_key_eh, 2);
1499
- rb_define_method(klass, "blank?", blank_eh, 0);
1500
- rb_define_method(klass, "attribute_nodes", attribute_nodes, 0);
1501
- rb_define_method(klass, "attribute", attr, 1);
1502
- rb_define_method(klass, "attribute_with_ns", attribute_with_ns, 2);
1503
- rb_define_method(klass, "namespace", namespace, 0);
1504
- rb_define_method(klass, "namespace_definitions", namespace_definitions, 0);
1505
- rb_define_method(klass, "namespace_scopes", namespace_scopes, 0);
1506
- rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
1507
- rb_define_method(klass, "dup", duplicate_node, -1);
1508
- rb_define_method(klass, "unlink", unlink_node, 0);
1509
- rb_define_method(klass, "internal_subset", internal_subset, 0);
1510
- rb_define_method(klass, "external_subset", external_subset, 0);
1511
- rb_define_method(klass, "create_internal_subset", create_internal_subset, 3);
1512
- rb_define_method(klass, "create_external_subset", create_external_subset, 3);
1513
- rb_define_method(klass, "pointer_id", pointer_id, 0);
1514
- rb_define_method(klass, "line", line, 0);
1515
- rb_define_method(klass, "native_content=", native_content, 1);
1516
-
1517
- rb_define_private_method(klass, "process_xincludes", process_xincludes, 1);
1518
- rb_define_private_method(klass, "in_context", in_context, 2);
1519
- rb_define_private_method(klass, "add_child_node", add_child, 1);
1520
- rb_define_private_method(klass, "add_previous_sibling_node", add_previous_sibling, 1);
1521
- rb_define_private_method(klass, "add_next_sibling_node", add_next_sibling, 1);
1522
- rb_define_private_method(klass, "replace_node", replace, 1);
1523
- rb_define_private_method(klass, "dump_html", dump_html, 0);
1524
- rb_define_private_method(klass, "native_write_to", native_write_to, 4);
1525
- rb_define_private_method(klass, "get", get, 1);
1526
- rb_define_private_method(klass, "set", set, 2);
1527
- rb_define_private_method(klass, "set_namespace", set_namespace, 1);
1528
- rb_define_private_method(klass, "compare", compare, 1);
1529
-
1530
- decorate = rb_intern("decorate");
1531
- decorate_bang = rb_intern("decorate!");
1776
+ cNokogiriXmlNode = rb_define_class_under(mNokogiriXml, "Node", rb_cObject);
1777
+
1778
+ rb_undef_alloc_func(cNokogiriXmlNode);
1779
+
1780
+ rb_define_singleton_method(cNokogiriXmlNode, "new", rb_xml_node_new, -1);
1781
+
1782
+ rb_define_method(cNokogiriXmlNode, "add_namespace_definition", add_namespace_definition, 2);
1783
+ rb_define_method(cNokogiriXmlNode, "node_name", get_name, 0);
1784
+ rb_define_method(cNokogiriXmlNode, "document", document, 0);
1785
+ rb_define_method(cNokogiriXmlNode, "node_name=", set_name, 1);
1786
+ rb_define_method(cNokogiriXmlNode, "parent", get_parent, 0);
1787
+ rb_define_method(cNokogiriXmlNode, "child", child, 0);
1788
+ rb_define_method(cNokogiriXmlNode, "first_element_child", first_element_child, 0);
1789
+ rb_define_method(cNokogiriXmlNode, "last_element_child", last_element_child, 0);
1790
+ rb_define_method(cNokogiriXmlNode, "children", children, 0);
1791
+ rb_define_method(cNokogiriXmlNode, "element_children", element_children, 0);
1792
+ rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
1793
+ rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
1794
+ rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
1795
+ rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
1796
+ rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
1797
+ rb_define_method(cNokogiriXmlNode, "path", noko_xml_node_path, 0);
1798
+ rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
1799
+ rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
1800
+ rb_define_method(cNokogiriXmlNode, "blank?", blank_eh, 0);
1801
+ rb_define_method(cNokogiriXmlNode, "attribute_nodes", attribute_nodes, 0);
1802
+ rb_define_method(cNokogiriXmlNode, "attribute", attr, 1);
1803
+ rb_define_method(cNokogiriXmlNode, "attribute_with_ns", attribute_with_ns, 2);
1804
+ rb_define_method(cNokogiriXmlNode, "namespace", noko_xml_node_namespace, 0);
1805
+ rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
1806
+ rb_define_method(cNokogiriXmlNode, "namespace_scopes", namespace_scopes, 0);
1807
+ rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
1808
+ rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
1809
+ rb_define_method(cNokogiriXmlNode, "unlink", unlink_node, 0);
1810
+ rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
1811
+ rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
1812
+ rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
1813
+ rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
1814
+ rb_define_method(cNokogiriXmlNode, "pointer_id", pointer_id, 0);
1815
+ rb_define_method(cNokogiriXmlNode, "line", line, 0);
1816
+ rb_define_method(cNokogiriXmlNode, "line=", set_line, 1);
1817
+ rb_define_method(cNokogiriXmlNode, "content", get_native_content, 0);
1818
+ rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
1819
+ rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
1820
+ rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
1821
+
1822
+ rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
1823
+ rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
1824
+ rb_define_private_method(cNokogiriXmlNode, "add_child_node", add_child, 1);
1825
+ rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
1826
+ rb_define_private_method(cNokogiriXmlNode, "add_next_sibling_node", add_next_sibling, 1);
1827
+ rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
1828
+ rb_define_private_method(cNokogiriXmlNode, "dump_html", dump_html, 0);
1829
+ rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
1830
+ rb_define_private_method(cNokogiriXmlNode, "get", get, 1);
1831
+ rb_define_private_method(cNokogiriXmlNode, "set", set, 2);
1832
+ rb_define_private_method(cNokogiriXmlNode, "set_namespace", set_namespace, 1);
1833
+ rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
1834
+
1835
+ id_decorate = rb_intern("decorate");
1836
+ id_decorate_bang = rb_intern("decorate!");
1532
1837
  }
1533
1838
 
1534
1839
  /* vim: set noet sw=4 sws=4 */