nokogiri 1.10.9 → 1.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +38 -0
  3. data/LICENSE-DEPENDENCIES.md +1632 -1022
  4. data/LICENSE.md +1 -1
  5. data/README.md +190 -95
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +34 -66
  8. data/ext/nokogiri/depend +38 -358
  9. data/ext/nokogiri/extconf.rb +909 -422
  10. data/ext/nokogiri/gumbo.c +610 -0
  11. data/ext/nokogiri/html4_document.c +171 -0
  12. data/ext/nokogiri/html4_element_description.c +299 -0
  13. data/ext/nokogiri/html4_entity_lookup.c +37 -0
  14. data/ext/nokogiri/html4_sax_parser.c +40 -0
  15. data/ext/nokogiri/html4_sax_parser_context.c +98 -0
  16. data/ext/nokogiri/html4_sax_push_parser.c +96 -0
  17. data/ext/nokogiri/libxml2_polyfill.c +114 -0
  18. data/ext/nokogiri/nokogiri.c +258 -105
  19. data/ext/nokogiri/nokogiri.h +207 -90
  20. data/ext/nokogiri/test_global_handlers.c +40 -0
  21. data/ext/nokogiri/xml_attr.c +18 -18
  22. data/ext/nokogiri/xml_attribute_decl.c +22 -22
  23. data/ext/nokogiri/xml_cdata.c +33 -33
  24. data/ext/nokogiri/xml_comment.c +19 -31
  25. data/ext/nokogiri/xml_document.c +499 -323
  26. data/ext/nokogiri/xml_document_fragment.c +17 -36
  27. data/ext/nokogiri/xml_dtd.c +65 -59
  28. data/ext/nokogiri/xml_element_content.c +63 -55
  29. data/ext/nokogiri/xml_element_decl.c +31 -31
  30. data/ext/nokogiri/xml_encoding_handler.c +54 -21
  31. data/ext/nokogiri/xml_entity_decl.c +37 -35
  32. data/ext/nokogiri/xml_entity_reference.c +17 -19
  33. data/ext/nokogiri/xml_namespace.c +131 -61
  34. data/ext/nokogiri/xml_node.c +1429 -723
  35. data/ext/nokogiri/xml_node_set.c +257 -225
  36. data/ext/nokogiri/xml_processing_instruction.c +18 -20
  37. data/ext/nokogiri/xml_reader.c +340 -231
  38. data/ext/nokogiri/xml_relax_ng.c +87 -99
  39. data/ext/nokogiri/xml_sax_parser.c +269 -176
  40. data/ext/nokogiri/xml_sax_parser_context.c +286 -152
  41. data/ext/nokogiri/xml_sax_push_parser.c +111 -64
  42. data/ext/nokogiri/xml_schema.c +132 -140
  43. data/ext/nokogiri/xml_syntax_error.c +52 -23
  44. data/ext/nokogiri/xml_text.c +37 -30
  45. data/ext/nokogiri/xml_xpath_context.c +373 -185
  46. data/ext/nokogiri/xslt_stylesheet.c +342 -191
  47. data/gumbo-parser/CHANGES.md +63 -0
  48. data/gumbo-parser/Makefile +129 -0
  49. data/gumbo-parser/THANKS +27 -0
  50. data/gumbo-parser/src/Makefile +34 -0
  51. data/gumbo-parser/src/README.md +41 -0
  52. data/gumbo-parser/src/ascii.c +75 -0
  53. data/gumbo-parser/src/ascii.h +115 -0
  54. data/gumbo-parser/src/attribute.c +42 -0
  55. data/gumbo-parser/src/attribute.h +17 -0
  56. data/gumbo-parser/src/char_ref.c +22225 -0
  57. data/gumbo-parser/src/char_ref.h +29 -0
  58. data/gumbo-parser/src/char_ref.rl +2154 -0
  59. data/gumbo-parser/src/error.c +658 -0
  60. data/gumbo-parser/src/error.h +152 -0
  61. data/gumbo-parser/src/foreign_attrs.c +103 -0
  62. data/gumbo-parser/src/foreign_attrs.gperf +27 -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/nokogiri_gumbo.h +953 -0
  66. data/gumbo-parser/src/parser.c +4932 -0
  67. data/gumbo-parser/src/parser.h +41 -0
  68. data/gumbo-parser/src/replacement.h +33 -0
  69. data/gumbo-parser/src/string_buffer.c +103 -0
  70. data/gumbo-parser/src/string_buffer.h +68 -0
  71. data/gumbo-parser/src/string_piece.c +48 -0
  72. data/gumbo-parser/src/svg_attrs.c +174 -0
  73. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  74. data/gumbo-parser/src/svg_tags.c +137 -0
  75. data/gumbo-parser/src/svg_tags.gperf +55 -0
  76. data/gumbo-parser/src/tag.c +223 -0
  77. data/gumbo-parser/src/tag_lookup.c +382 -0
  78. data/gumbo-parser/src/tag_lookup.gperf +170 -0
  79. data/gumbo-parser/src/tag_lookup.h +13 -0
  80. data/gumbo-parser/src/token_buffer.c +79 -0
  81. data/gumbo-parser/src/token_buffer.h +71 -0
  82. data/gumbo-parser/src/token_type.h +17 -0
  83. data/gumbo-parser/src/tokenizer.c +3464 -0
  84. data/gumbo-parser/src/tokenizer.h +112 -0
  85. data/gumbo-parser/src/tokenizer_states.h +339 -0
  86. data/gumbo-parser/src/utf8.c +245 -0
  87. data/gumbo-parser/src/utf8.h +164 -0
  88. data/gumbo-parser/src/util.c +66 -0
  89. data/gumbo-parser/src/util.h +34 -0
  90. data/gumbo-parser/src/vector.c +111 -0
  91. data/gumbo-parser/src/vector.h +45 -0
  92. data/lib/nokogiri/class_resolver.rb +67 -0
  93. data/lib/nokogiri/css/node.rb +14 -8
  94. data/lib/nokogiri/css/parser.rb +399 -377
  95. data/lib/nokogiri/css/parser.y +250 -245
  96. data/lib/nokogiri/css/parser_extras.rb +16 -71
  97. data/lib/nokogiri/css/selector_cache.rb +38 -0
  98. data/lib/nokogiri/css/syntax_error.rb +3 -1
  99. data/lib/nokogiri/css/tokenizer.rb +7 -5
  100. data/lib/nokogiri/css/tokenizer.rex +11 -9
  101. data/lib/nokogiri/css/xpath_visitor.rb +242 -96
  102. data/lib/nokogiri/css.rb +122 -17
  103. data/lib/nokogiri/decorators/slop.rb +11 -11
  104. data/lib/nokogiri/encoding_handler.rb +57 -0
  105. data/lib/nokogiri/extension.rb +32 -0
  106. data/lib/nokogiri/gumbo.rb +15 -0
  107. data/lib/nokogiri/html.rb +38 -27
  108. data/lib/nokogiri/{html → html4}/builder.rb +4 -2
  109. data/lib/nokogiri/html4/document.rb +235 -0
  110. data/lib/nokogiri/html4/document_fragment.rb +166 -0
  111. data/lib/nokogiri/{html → html4}/element_description.rb +3 -1
  112. data/lib/nokogiri/html4/element_description_defaults.rb +2040 -0
  113. data/lib/nokogiri/html4/encoding_reader.rb +121 -0
  114. data/lib/nokogiri/{html → html4}/entity_lookup.rb +4 -2
  115. data/lib/nokogiri/html4/sax/parser.rb +48 -0
  116. data/lib/nokogiri/html4/sax/parser_context.rb +15 -0
  117. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
  118. data/lib/nokogiri/html4.rb +42 -0
  119. data/lib/nokogiri/html5/builder.rb +40 -0
  120. data/lib/nokogiri/html5/document.rb +199 -0
  121. data/lib/nokogiri/html5/document_fragment.rb +200 -0
  122. data/lib/nokogiri/html5/node.rb +103 -0
  123. data/lib/nokogiri/html5.rb +368 -0
  124. data/lib/nokogiri/jruby/dependencies.rb +3 -0
  125. data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
  126. data/lib/nokogiri/syntax_error.rb +2 -0
  127. data/lib/nokogiri/version/constant.rb +6 -0
  128. data/lib/nokogiri/version/info.rb +224 -0
  129. data/lib/nokogiri/version.rb +3 -108
  130. data/lib/nokogiri/xml/attr.rb +55 -3
  131. data/lib/nokogiri/xml/attribute_decl.rb +6 -2
  132. data/lib/nokogiri/xml/builder.rb +83 -35
  133. data/lib/nokogiri/xml/cdata.rb +3 -1
  134. data/lib/nokogiri/xml/character_data.rb +2 -0
  135. data/lib/nokogiri/xml/document.rb +359 -130
  136. data/lib/nokogiri/xml/document_fragment.rb +170 -54
  137. data/lib/nokogiri/xml/dtd.rb +4 -2
  138. data/lib/nokogiri/xml/element_content.rb +12 -2
  139. data/lib/nokogiri/xml/element_decl.rb +6 -2
  140. data/lib/nokogiri/xml/entity_decl.rb +7 -3
  141. data/lib/nokogiri/xml/entity_reference.rb +2 -0
  142. data/lib/nokogiri/xml/namespace.rb +44 -0
  143. data/lib/nokogiri/xml/node/save_options.rb +23 -8
  144. data/lib/nokogiri/xml/node.rb +1168 -420
  145. data/lib/nokogiri/xml/node_set.rb +145 -67
  146. data/lib/nokogiri/xml/notation.rb +13 -0
  147. data/lib/nokogiri/xml/parse_options.rb +145 -52
  148. data/lib/nokogiri/xml/pp/character_data.rb +9 -6
  149. data/lib/nokogiri/xml/pp/node.rb +47 -30
  150. data/lib/nokogiri/xml/pp.rb +4 -2
  151. data/lib/nokogiri/xml/processing_instruction.rb +4 -1
  152. data/lib/nokogiri/xml/reader.rb +68 -41
  153. data/lib/nokogiri/xml/relax_ng.rb +60 -17
  154. data/lib/nokogiri/xml/sax/document.rb +198 -111
  155. data/lib/nokogiri/xml/sax/parser.rb +144 -67
  156. data/lib/nokogiri/xml/sax/parser_context.rb +119 -6
  157. data/lib/nokogiri/xml/sax/push_parser.rb +9 -5
  158. data/lib/nokogiri/xml/sax.rb +54 -4
  159. data/lib/nokogiri/xml/schema.rb +116 -39
  160. data/lib/nokogiri/xml/searchable.rb +139 -95
  161. data/lib/nokogiri/xml/syntax_error.rb +29 -5
  162. data/lib/nokogiri/xml/text.rb +2 -0
  163. data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
  164. data/lib/nokogiri/xml/xpath.rb +15 -4
  165. data/lib/nokogiri/xml/xpath_context.rb +15 -4
  166. data/lib/nokogiri/xml.rb +45 -55
  167. data/lib/nokogiri/xslt/stylesheet.rb +32 -8
  168. data/lib/nokogiri/xslt.rb +103 -30
  169. data/lib/nokogiri.rb +59 -75
  170. data/lib/xsd/xmlparser/nokogiri.rb +32 -29
  171. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  172. data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
  173. data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
  174. data/patches/libxml2/0019-xpath-Use-separate-static-hash-table-for-standard-fu.patch +244 -0
  175. data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
  176. data/ports/archives/libxml2-2.13.6.tar.xz +0 -0
  177. data/ports/archives/libxslt-1.1.42.tar.xz +0 -0
  178. metadata +123 -295
  179. data/ext/nokogiri/html_document.c +0 -170
  180. data/ext/nokogiri/html_document.h +0 -10
  181. data/ext/nokogiri/html_element_description.c +0 -279
  182. data/ext/nokogiri/html_element_description.h +0 -10
  183. data/ext/nokogiri/html_entity_lookup.c +0 -32
  184. data/ext/nokogiri/html_entity_lookup.h +0 -8
  185. data/ext/nokogiri/html_sax_parser_context.c +0 -116
  186. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  187. data/ext/nokogiri/html_sax_push_parser.c +0 -87
  188. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  189. data/ext/nokogiri/xml_attr.h +0 -9
  190. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  191. data/ext/nokogiri/xml_cdata.h +0 -9
  192. data/ext/nokogiri/xml_comment.h +0 -9
  193. data/ext/nokogiri/xml_document.h +0 -23
  194. data/ext/nokogiri/xml_document_fragment.h +0 -10
  195. data/ext/nokogiri/xml_dtd.h +0 -10
  196. data/ext/nokogiri/xml_element_content.h +0 -10
  197. data/ext/nokogiri/xml_element_decl.h +0 -9
  198. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  199. data/ext/nokogiri/xml_entity_decl.h +0 -10
  200. data/ext/nokogiri/xml_entity_reference.h +0 -9
  201. data/ext/nokogiri/xml_io.c +0 -61
  202. data/ext/nokogiri/xml_io.h +0 -11
  203. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  204. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  205. data/ext/nokogiri/xml_namespace.h +0 -14
  206. data/ext/nokogiri/xml_node.h +0 -13
  207. data/ext/nokogiri/xml_node_set.h +0 -12
  208. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  209. data/ext/nokogiri/xml_reader.h +0 -10
  210. data/ext/nokogiri/xml_relax_ng.h +0 -9
  211. data/ext/nokogiri/xml_sax_parser.h +0 -39
  212. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  213. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  214. data/ext/nokogiri/xml_schema.h +0 -9
  215. data/ext/nokogiri/xml_syntax_error.h +0 -13
  216. data/ext/nokogiri/xml_text.h +0 -9
  217. data/ext/nokogiri/xml_xpath_context.h +0 -10
  218. data/ext/nokogiri/xslt_stylesheet.h +0 -14
  219. data/lib/nokogiri/html/document.rb +0 -335
  220. data/lib/nokogiri/html/document_fragment.rb +0 -49
  221. data/lib/nokogiri/html/element_description_defaults.rb +0 -671
  222. data/lib/nokogiri/html/sax/parser.rb +0 -62
  223. data/lib/nokogiri/html/sax/parser_context.rb +0 -16
  224. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  225. data/patches/libxml2/0004-libxml2.la-is-in-top_builddir.patch +0 -25
  226. data/patches/libxml2/0005-Fix-infinite-loop-in-xmlStringLenDecodeEntities.patch +0 -32
  227. data/ports/archives/libxml2-2.9.10.tar.gz +0 -0
  228. data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
  229. /data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
  230. /data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
@@ -1,12 +1,11 @@
1
- #include <xml_node_set.h>
2
- #include <xml_namespace.h>
3
- #include <libxml/xpathInternals.h>
1
+ #include <nokogiri.h>
4
2
 
5
- static ID decorate ;
6
- static void xpath_node_set_del(xmlNodeSetPtr cur, xmlNodePtr val);
3
+ VALUE cNokogiriXmlNodeSet ;
7
4
 
5
+ static ID decorate ;
8
6
 
9
- static void Check_Node_Set_Node_Type(VALUE node)
7
+ static void
8
+ Check_Node_Set_Node_Type(VALUE node)
10
9
  {
11
10
  if (!(rb_obj_is_kind_of(node, cNokogiriXmlNode) ||
12
11
  rb_obj_is_kind_of(node, cNokogiriXmlNamespace))) {
@@ -15,54 +14,122 @@ static void Check_Node_Set_Node_Type(VALUE node)
15
14
  }
16
15
 
17
16
 
18
- static void deallocate(xmlNodeSetPtr node_set)
17
+ static
18
+ VALUE
19
+ ruby_object_get(xmlNodePtr c_node)
20
+ {
21
+ /* see xmlElementType in libxml2 tree.h */
22
+ switch (c_node->type) {
23
+ case XML_NAMESPACE_DECL:
24
+ /* _private is later in the namespace struct */
25
+ return (VALUE)(((xmlNsPtr)c_node)->_private);
26
+
27
+ case XML_DOCUMENT_NODE:
28
+ case XML_HTML_DOCUMENT_NODE:
29
+ /* in documents we use _private to store a tuple */
30
+ if (DOC_RUBY_OBJECT_TEST(((xmlDocPtr)c_node))) {
31
+ return DOC_RUBY_OBJECT((xmlDocPtr)c_node);
32
+ }
33
+ return (VALUE)NULL;
34
+
35
+ default:
36
+ return (VALUE)(c_node->_private);
37
+ }
38
+ }
39
+
40
+
41
+ static void
42
+ xml_node_set_mark(void *data)
19
43
  {
44
+ xmlNodeSetPtr node_set = data;
45
+ VALUE rb_node;
46
+ int jnode;
47
+
48
+ for (jnode = 0; jnode < node_set->nodeNr; jnode++) {
49
+ rb_node = ruby_object_get(node_set->nodeTab[jnode]);
50
+ if (rb_node) {
51
+ rb_gc_mark(rb_node);
52
+ }
53
+ }
54
+ }
55
+
56
+ static void
57
+ xml_node_set_deallocate(void *data)
58
+ {
59
+ xmlNodeSetPtr node_set = data;
20
60
  /*
21
- *
22
- * since xpath queries return copies of the xmlNs structs,
23
- * xmlXPathFreeNodeSet() frees those xmlNs structs that are in the
24
- * NodeSet.
25
- *
26
- * this is bad if someone is still trying to use the Namespace object wrapped
27
- * around the xmlNs, so we need to avoid that.
28
- *
29
- * here we reproduce xmlXPathFreeNodeSet() without the xmlNs logic.
30
- *
31
- * this doesn't cause a leak because Namespace objects that are in an XPath
32
- * query NodeSet are given their own lifecycle in
33
- * Nokogiri_wrap_xml_namespace().
61
+ * For reasons outlined in xml_namespace.c, here we reproduce xmlXPathFreeNodeSet() except for the
62
+ * offending call to xmlXPathNodeSetFreeNs().
34
63
  */
35
- NOKOGIRI_DEBUG_START(node_set) ;
36
- if (node_set->nodeTab != NULL)
64
+ if (node_set->nodeTab != NULL) {
37
65
  xmlFree(node_set->nodeTab);
66
+ }
38
67
 
39
68
  xmlFree(node_set);
40
- NOKOGIRI_DEBUG_END(node_set) ;
41
69
  }
42
70
 
43
- static VALUE allocate(VALUE klass)
71
+ static const rb_data_type_t xml_node_set_type = {
72
+ .wrap_struct_name = "xmlNodeSet",
73
+ .function = {
74
+ .dmark = xml_node_set_mark,
75
+ .dfree = xml_node_set_deallocate,
76
+ },
77
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
78
+ };
79
+
80
+ static VALUE
81
+ xml_node_set_allocate(VALUE klass)
44
82
  {
45
- return Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL), Qnil);
83
+ return TypedData_Wrap_Struct(klass, &xml_node_set_type, xmlXPathNodeSetCreate(NULL));
46
84
  }
47
85
 
86
+ /* :nodoc: */
87
+ static VALUE
88
+ rb_xml_node_set_initialize_copy(VALUE rb_self, VALUE rb_other)
89
+ {
90
+ xmlNodeSetPtr c_self, c_other;
91
+ VALUE rb_document;
48
92
 
49
- /*
50
- * call-seq:
51
- * dup
52
- *
53
- * Duplicate this NodeSet. Note that the Nodes contained in the NodeSet are not
54
- * duplicated (similar to how Array and other Enumerable classes work).
55
- */
56
- static VALUE duplicate(VALUE self)
93
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
94
+ TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);
95
+
96
+ xmlXPathNodeSetMerge(c_self, c_other);
97
+
98
+ rb_document = rb_iv_get(rb_other, "@document");
99
+ if (!NIL_P(rb_document)) {
100
+ rb_iv_set(rb_self, "@document", rb_document);
101
+ rb_funcall(rb_document, decorate, 1, rb_self);
102
+ }
103
+
104
+ return rb_self;
105
+ }
106
+
107
+ static void
108
+ xpath_node_set_del(xmlNodeSetPtr cur, xmlNodePtr val)
57
109
  {
58
- xmlNodeSetPtr node_set;
59
- xmlNodeSetPtr dupl;
110
+ /*
111
+ * For reasons outlined in xml_namespace.c, here we reproduce xmlXPathNodeSetDel() except for the
112
+ * offending call to xmlXPathNodeSetFreeNs().
113
+ */
114
+ int i;
60
115
 
61
- Data_Get_Struct(self, xmlNodeSet, node_set);
116
+ if (cur == NULL) { return; }
117
+ if (val == NULL) { return; }
62
118
 
63
- dupl = xmlXPathNodeSetMerge(NULL, node_set);
119
+ /*
120
+ * find node in nodeTab
121
+ */
122
+ for (i = 0; i < cur->nodeNr; i++)
123
+ if (cur->nodeTab[i] == val) { break; }
64
124
 
65
- return Nokogiri_wrap_xml_node_set(dupl, rb_iv_get(self, "@document"));
125
+ if (i >= cur->nodeNr) { /* not found */
126
+ return;
127
+ }
128
+ cur->nodeNr--;
129
+ for (; i < cur->nodeNr; i++) {
130
+ cur->nodeTab[i] = cur->nodeTab[i + 1];
131
+ }
132
+ cur->nodeTab[cur->nodeNr] = NULL;
66
133
  }
67
134
 
68
135
  /*
@@ -71,13 +138,14 @@ static VALUE duplicate(VALUE self)
71
138
  *
72
139
  * Get the length of the node set
73
140
  */
74
- static VALUE length(VALUE self)
141
+ static VALUE
142
+ length(VALUE rb_self)
75
143
  {
76
- xmlNodeSetPtr node_set;
144
+ xmlNodeSetPtr c_self;
77
145
 
78
- Data_Get_Struct(self, xmlNodeSet, node_set);
146
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
79
147
 
80
- return node_set ? INT2NUM(node_set->nodeNr) : INT2NUM(0);
148
+ return c_self ? INT2NUM(c_self->nodeNr) : INT2NUM(0);
81
149
  }
82
150
 
83
151
  /*
@@ -86,19 +154,20 @@ static VALUE length(VALUE self)
86
154
  *
87
155
  * Append +node+ to the NodeSet.
88
156
  */
89
- static VALUE push(VALUE self, VALUE rb_node)
157
+ static VALUE
158
+ push(VALUE rb_self, VALUE rb_node)
90
159
  {
91
- xmlNodeSetPtr node_set;
160
+ xmlNodeSetPtr c_self;
92
161
  xmlNodePtr node;
93
162
 
94
163
  Check_Node_Set_Node_Type(rb_node);
95
164
 
96
- Data_Get_Struct(self, xmlNodeSet, node_set);
97
- Data_Get_Struct(rb_node, xmlNode, node);
165
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
166
+ Noko_Node_Get_Struct(rb_node, xmlNode, node);
98
167
 
99
- xmlXPathNodeSetAdd(node_set, node);
168
+ xmlXPathNodeSetAdd(c_self, node);
100
169
 
101
- return self;
170
+ return rb_self;
102
171
  }
103
172
 
104
173
  /*
@@ -109,18 +178,18 @@ static VALUE push(VALUE self, VALUE rb_node)
109
178
  * if found, otherwise returns nil.
110
179
  */
111
180
  static VALUE
112
- delete(VALUE self, VALUE rb_node)
181
+ delete (VALUE rb_self, VALUE rb_node)
113
182
  {
114
- xmlNodeSetPtr node_set;
183
+ xmlNodeSetPtr c_self;
115
184
  xmlNodePtr node;
116
185
 
117
186
  Check_Node_Set_Node_Type(rb_node);
118
187
 
119
- Data_Get_Struct(self, xmlNodeSet, node_set);
120
- Data_Get_Struct(rb_node, xmlNode, node);
188
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
189
+ Noko_Node_Get_Struct(rb_node, xmlNode, node);
121
190
 
122
- if (xmlXPathNodeSetContains(node_set, node)) {
123
- xpath_node_set_del(node_set, node);
191
+ if (xmlXPathNodeSetContains(c_self, node)) {
192
+ xpath_node_set_del(c_self, node);
124
193
  return rb_node;
125
194
  }
126
195
  return Qnil ;
@@ -133,19 +202,21 @@ delete(VALUE self, VALUE rb_node)
133
202
  *
134
203
  * Set Intersection — Returns a new NodeSet containing nodes common to the two NodeSets.
135
204
  */
136
- static VALUE intersection(VALUE self, VALUE rb_other)
205
+ static VALUE
206
+ intersection(VALUE rb_self, VALUE rb_other)
137
207
  {
138
- xmlNodeSetPtr node_set, other ;
208
+ xmlNodeSetPtr c_self, c_other ;
139
209
  xmlNodeSetPtr intersection;
140
210
 
141
- if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
211
+ if (!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet)) {
142
212
  rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
213
+ }
143
214
 
144
- Data_Get_Struct(self, xmlNodeSet, node_set);
145
- Data_Get_Struct(rb_other, xmlNodeSet, other);
215
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
216
+ TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);
146
217
 
147
- intersection = xmlXPathIntersection(node_set, other);
148
- return Nokogiri_wrap_xml_node_set(intersection, rb_iv_get(self, "@document"));
218
+ intersection = xmlXPathIntersection(c_self, c_other);
219
+ return noko_xml_node_set_wrap(intersection, rb_iv_get(rb_self, "@document"));
149
220
  }
150
221
 
151
222
 
@@ -155,17 +226,18 @@ static VALUE intersection(VALUE self, VALUE rb_other)
155
226
  *
156
227
  * Returns true if any member of node set equals +node+.
157
228
  */
158
- static VALUE include_eh(VALUE self, VALUE rb_node)
229
+ static VALUE
230
+ include_eh(VALUE rb_self, VALUE rb_node)
159
231
  {
160
- xmlNodeSetPtr node_set;
232
+ xmlNodeSetPtr c_self;
161
233
  xmlNodePtr node;
162
234
 
163
235
  Check_Node_Set_Node_Type(rb_node);
164
236
 
165
- Data_Get_Struct(self, xmlNodeSet, node_set);
166
- Data_Get_Struct(rb_node, xmlNode, node);
237
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
238
+ Noko_Node_Get_Struct(rb_node, xmlNode, node);
167
239
 
168
- return (xmlXPathNodeSetContains(node_set, node) ? Qtrue : Qfalse);
240
+ return (xmlXPathNodeSetContains(c_self, node) ? Qtrue : Qfalse);
169
241
  }
170
242
 
171
243
 
@@ -176,21 +248,23 @@ static VALUE include_eh(VALUE self, VALUE rb_node)
176
248
  * Returns a new set built by merging the set and the elements of the given
177
249
  * set.
178
250
  */
179
- static VALUE set_union(VALUE self, VALUE rb_other)
251
+ static VALUE
252
+ rb_xml_node_set_union(VALUE rb_self, VALUE rb_other)
180
253
  {
181
- xmlNodeSetPtr node_set, other;
182
- xmlNodeSetPtr new;
254
+ xmlNodeSetPtr c_self, c_other;
255
+ xmlNodeSetPtr c_new_node_set;
183
256
 
184
- if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
257
+ if (!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet)) {
185
258
  rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
259
+ }
186
260
 
187
- Data_Get_Struct(self, xmlNodeSet, node_set);
188
- Data_Get_Struct(rb_other, xmlNodeSet, other);
261
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
262
+ TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);
189
263
 
190
- new = xmlXPathNodeSetMerge(NULL, node_set);
191
- new = xmlXPathNodeSetMerge(new, other);
264
+ c_new_node_set = xmlXPathNodeSetMerge(NULL, c_self);
265
+ c_new_node_set = xmlXPathNodeSetMerge(c_new_node_set, c_other);
192
266
 
193
- return Nokogiri_wrap_xml_node_set(new, rb_iv_get(self, "@document"));
267
+ return noko_xml_node_set_wrap(c_new_node_set, rb_iv_get(rb_self, "@document"));
194
268
  }
195
269
 
196
270
  /*
@@ -200,62 +274,66 @@ static VALUE set_union(VALUE self, VALUE rb_other)
200
274
  * Difference - returns a new NodeSet that is a copy of this NodeSet, removing
201
275
  * each item that also appears in +node_set+
202
276
  */
203
- static VALUE minus(VALUE self, VALUE rb_other)
277
+ static VALUE
278
+ minus(VALUE rb_self, VALUE rb_other)
204
279
  {
205
- xmlNodeSetPtr node_set, other;
280
+ xmlNodeSetPtr c_self, c_other;
206
281
  xmlNodeSetPtr new;
207
282
  int j ;
208
283
 
209
- if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
284
+ if (!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet)) {
210
285
  rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
286
+ }
211
287
 
212
- Data_Get_Struct(self, xmlNodeSet, node_set);
213
- Data_Get_Struct(rb_other, xmlNodeSet, other);
288
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
289
+ TypedData_Get_Struct(rb_other, xmlNodeSet, &xml_node_set_type, c_other);
214
290
 
215
- new = xmlXPathNodeSetMerge(NULL, node_set);
216
- for (j = 0 ; j < other->nodeNr ; ++j) {
217
- xpath_node_set_del(new, other->nodeTab[j]);
291
+ new = xmlXPathNodeSetMerge(NULL, c_self);
292
+ for (j = 0 ; j < c_other->nodeNr ; ++j) {
293
+ xpath_node_set_del(new, c_other->nodeTab[j]);
218
294
  }
219
295
 
220
- return Nokogiri_wrap_xml_node_set(new, rb_iv_get(self, "@document"));
296
+ return noko_xml_node_set_wrap(new, rb_iv_get(rb_self, "@document"));
221
297
  }
222
298
 
223
299
 
224
- static VALUE index_at(VALUE self, long offset)
300
+ static VALUE
301
+ index_at(VALUE rb_self, long offset)
225
302
  {
226
- xmlNodeSetPtr node_set;
303
+ xmlNodeSetPtr c_self;
227
304
 
228
- Data_Get_Struct(self, xmlNodeSet, node_set);
305
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
229
306
 
230
- if (offset >= node_set->nodeNr || abs((int)offset) > node_set->nodeNr) {
307
+ if (offset >= c_self->nodeNr || abs((int)offset) > c_self->nodeNr) {
231
308
  return Qnil;
232
309
  }
233
310
 
234
- if (offset < 0) { offset += node_set->nodeNr ; }
311
+ if (offset < 0) { offset += c_self->nodeNr ; }
235
312
 
236
- return Nokogiri_wrap_xml_node_set_node(node_set->nodeTab[offset], self);
313
+ return noko_xml_node_wrap_node_set_result(c_self->nodeTab[offset], rb_self);
237
314
  }
238
315
 
239
- static VALUE subseq(VALUE self, long beg, long len)
316
+ static VALUE
317
+ subseq(VALUE rb_self, long beg, long len)
240
318
  {
241
319
  long j;
242
- xmlNodeSetPtr node_set;
320
+ xmlNodeSetPtr c_self;
243
321
  xmlNodeSetPtr new_set ;
244
322
 
245
- Data_Get_Struct(self, xmlNodeSet, node_set);
323
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
246
324
 
247
- if (beg > node_set->nodeNr) return Qnil ;
248
- if (beg < 0 || len < 0) return Qnil ;
325
+ if (beg > c_self->nodeNr) { return Qnil ; }
326
+ if (beg < 0 || len < 0) { return Qnil ; }
249
327
 
250
- if ((beg + len) > node_set->nodeNr) {
251
- len = node_set->nodeNr - beg ;
328
+ if ((beg + len) > c_self->nodeNr) {
329
+ len = c_self->nodeNr - beg ;
252
330
  }
253
331
 
254
332
  new_set = xmlXPathNodeSetCreate(NULL);
255
- for (j = beg ; j < beg+len ; ++j) {
256
- xmlXPathNodeSetAddUnique(new_set, node_set->nodeTab[j]);
333
+ for (j = beg ; j < beg + len ; ++j) {
334
+ xmlXPathNodeSetAddUnique(new_set, c_self->nodeTab[j]);
257
335
  }
258
- return Nokogiri_wrap_xml_node_set(new_set, rb_iv_get(self, "@document"));
336
+ return noko_xml_node_set_wrap(new_set, rb_iv_get(rb_self, "@document"));
259
337
  }
260
338
 
261
339
  /*
@@ -273,21 +351,22 @@ static VALUE subseq(VALUE self, long beg, long len)
273
351
  * count backward from the end of the +node_set+ (-1 is the last node). Returns
274
352
  * nil if the +index+ (or +start+) are out of range.
275
353
  */
276
- static VALUE slice(int argc, VALUE *argv, VALUE self)
354
+ static VALUE
355
+ slice(int argc, VALUE *argv, VALUE rb_self)
277
356
  {
278
357
  VALUE arg ;
279
358
  long beg, len ;
280
- xmlNodeSetPtr node_set;
359
+ xmlNodeSetPtr c_self;
281
360
 
282
- Data_Get_Struct(self, xmlNodeSet, node_set);
361
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
283
362
 
284
363
  if (argc == 2) {
285
364
  beg = NUM2LONG(argv[0]);
286
365
  len = NUM2LONG(argv[1]);
287
366
  if (beg < 0) {
288
- beg += node_set->nodeNr ;
367
+ beg += c_self->nodeNr ;
289
368
  }
290
- return subseq(self, beg, len);
369
+ return subseq(rb_self, beg, len);
291
370
  }
292
371
 
293
372
  if (argc != 1) {
@@ -296,20 +375,20 @@ static VALUE slice(int argc, VALUE *argv, VALUE self)
296
375
  arg = argv[0];
297
376
 
298
377
  if (FIXNUM_P(arg)) {
299
- return index_at(self, FIX2LONG(arg));
378
+ return index_at(rb_self, FIX2LONG(arg));
300
379
  }
301
380
 
302
381
  /* if arg is Range */
303
- switch (rb_range_beg_len(arg, &beg, &len, (long)node_set->nodeNr, 0)) {
304
- case Qfalse:
305
- break;
306
- case Qnil:
307
- return Qnil;
308
- default:
309
- return subseq(self, beg, len);
382
+ switch (rb_range_beg_len(arg, &beg, &len, (long)c_self->nodeNr, 0)) {
383
+ case Qfalse:
384
+ break;
385
+ case Qnil:
386
+ return Qnil;
387
+ default:
388
+ return subseq(rb_self, beg, len);
310
389
  }
311
390
 
312
- return index_at(self, NUM2LONG(arg));
391
+ return index_at(rb_self, NUM2LONG(arg));
313
392
  }
314
393
 
315
394
 
@@ -319,18 +398,19 @@ static VALUE slice(int argc, VALUE *argv, VALUE self)
319
398
  *
320
399
  * Return this list as an Array
321
400
  */
322
- static VALUE to_array(VALUE self, VALUE rb_node)
401
+ static VALUE
402
+ to_array(VALUE rb_self)
323
403
  {
324
- xmlNodeSetPtr node_set ;
404
+ xmlNodeSetPtr c_self ;
325
405
  VALUE list;
326
406
  int i;
327
407
 
328
- Data_Get_Struct(self, xmlNodeSet, node_set);
408
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
329
409
 
330
- list = rb_ary_new2(node_set->nodeNr);
331
- for(i = 0; i < node_set->nodeNr; i++) {
332
- VALUE elt = Nokogiri_wrap_xml_node_set_node(node_set->nodeTab[i], self);
333
- rb_ary_push( list, elt );
410
+ list = rb_ary_new2(c_self->nodeNr);
411
+ for (i = 0; i < c_self->nodeNr; i++) {
412
+ VALUE elt = noko_xml_node_wrap_node_set_result(c_self->nodeTab[i], rb_self);
413
+ rb_ary_push(list, elt);
334
414
  }
335
415
 
336
416
  return list;
@@ -342,145 +422,97 @@ static VALUE to_array(VALUE self, VALUE rb_node)
342
422
  *
343
423
  * Unlink this NodeSet and all Node objects it contains from their current context.
344
424
  */
345
- static VALUE unlink_nodeset(VALUE self)
425
+ static VALUE
426
+ unlink_nodeset(VALUE rb_self)
346
427
  {
347
- xmlNodeSetPtr node_set;
428
+ xmlNodeSetPtr c_self;
348
429
  int j, nodeNr ;
349
430
 
350
- Data_Get_Struct(self, xmlNodeSet, node_set);
431
+ TypedData_Get_Struct(rb_self, xmlNodeSet, &xml_node_set_type, c_self);
351
432
 
352
- nodeNr = node_set->nodeNr ;
433
+ nodeNr = c_self->nodeNr ;
353
434
  for (j = 0 ; j < nodeNr ; j++) {
354
- if (! NOKOGIRI_NAMESPACE_EH(node_set->nodeTab[j])) {
435
+ if (! NOKOGIRI_NAMESPACE_EH(c_self->nodeTab[j])) {
355
436
  VALUE node ;
356
437
  xmlNodePtr node_ptr;
357
- node = Nokogiri_wrap_xml_node(Qnil, node_set->nodeTab[j]);
438
+ node = noko_xml_node_wrap(Qnil, c_self->nodeTab[j]);
358
439
  rb_funcall(node, rb_intern("unlink"), 0); /* modifies the C struct out from under the object */
359
- Data_Get_Struct(node, xmlNode, node_ptr);
360
- node_set->nodeTab[j] = node_ptr ;
361
- }
362
- }
363
- return self ;
364
- }
365
-
366
-
367
- static void reify_node_set_namespaces(VALUE self)
368
- {
369
- /*
370
- * as mentioned in deallocate() above, xmlNs structs returned in an XPath
371
- * NodeSet are duplicates, and we don't clean them up at deallocate() time.
372
- *
373
- * as a result, we need to make sure the Ruby manages this memory. we do this
374
- * by forcing the creation of a Ruby object wrapped around the xmlNs.
375
- *
376
- * we also have to make sure that the NodeSet has a reference to the
377
- * Namespace object, otherwise GC will kick in and the Namespace won't be
378
- * marked.
379
- *
380
- * we *could* do this safely with *all* the nodes in the NodeSet, but we only
381
- * *need* to do it for xmlNs structs, and so you get the code we have here.
382
- */
383
- int j ;
384
- xmlNodeSetPtr node_set ;
385
- VALUE namespace_cache ;
386
-
387
- Data_Get_Struct(self, xmlNodeSet, node_set);
388
-
389
- namespace_cache = rb_iv_get(self, "@namespace_cache");
390
-
391
- for (j = 0 ; j < node_set->nodeNr ; j++) {
392
- if (NOKOGIRI_NAMESPACE_EH(node_set->nodeTab[j])) {
393
- rb_ary_push(namespace_cache, Nokogiri_wrap_xml_node_set_node(node_set->nodeTab[j], self));
440
+ Noko_Node_Get_Struct(node, xmlNode, node_ptr);
441
+ c_self->nodeTab[j] = node_ptr ;
394
442
  }
395
443
  }
444
+ return rb_self ;
396
445
  }
397
446
 
398
447
 
399
- VALUE Nokogiri_wrap_xml_node_set(xmlNodeSetPtr node_set, VALUE document)
448
+ VALUE
449
+ noko_xml_node_set_wrap(xmlNodeSetPtr c_node_set, VALUE document)
400
450
  {
401
- VALUE new_set ;
451
+ int j;
452
+ VALUE rb_node_set ;
402
453
 
403
- if (node_set == NULL) {
404
- node_set = xmlXPathNodeSetCreate(NULL);
454
+ if (c_node_set == NULL) {
455
+ rb_node_set = xml_node_set_allocate(cNokogiriXmlNodeSet);
456
+ } else {
457
+ rb_node_set = TypedData_Wrap_Struct(cNokogiriXmlNodeSet, &xml_node_set_type, c_node_set);
405
458
  }
406
459
 
407
- new_set = Data_Wrap_Struct(cNokogiriXmlNodeSet, 0, deallocate, node_set);
408
-
409
460
  if (!NIL_P(document)) {
410
- rb_iv_set(new_set, "@document", document);
411
- rb_funcall(document, decorate, 1, new_set);
461
+ rb_iv_set(rb_node_set, "@document", document);
462
+ rb_funcall(document, decorate, 1, rb_node_set);
412
463
  }
413
464
 
414
- rb_iv_set(new_set, "@namespace_cache", rb_ary_new());
415
- reify_node_set_namespaces(new_set);
465
+ if (c_node_set) {
466
+ /* create ruby objects for all the results, so they'll be marked during the GC mark phase */
467
+ for (j = 0 ; j < c_node_set->nodeNr ; j++) {
468
+ noko_xml_node_wrap_node_set_result(c_node_set->nodeTab[j], rb_node_set);
469
+ }
470
+ }
416
471
 
417
- return new_set ;
472
+ return rb_node_set ;
418
473
  }
419
474
 
420
- VALUE Nokogiri_wrap_xml_node_set_node(xmlNodePtr node, VALUE node_set)
421
- {
422
- xmlDocPtr document ;
423
475
 
476
+ VALUE
477
+ noko_xml_node_wrap_node_set_result(xmlNodePtr node, VALUE node_set)
478
+ {
424
479
  if (NOKOGIRI_NAMESPACE_EH(node)) {
425
- Data_Get_Struct(rb_iv_get(node_set, "@document"), xmlDoc, document);
426
- return Nokogiri_wrap_xml_namespace(document, (xmlNsPtr)node);
480
+ return noko_xml_namespace_wrap_xpath_copy((xmlNsPtr)node);
427
481
  } else {
428
- return Nokogiri_wrap_xml_node(Qnil, node);
482
+ return noko_xml_node_wrap(Qnil, node);
429
483
  }
430
484
  }
431
485
 
432
486
 
433
- static void xpath_node_set_del(xmlNodeSetPtr cur, xmlNodePtr val)
487
+ xmlNodeSetPtr
488
+ noko_xml_node_set_unwrap(VALUE rb_node_set)
434
489
  {
435
- /*
436
- * as mentioned a few times above, we do not want to free xmlNs structs
437
- * outside of the Namespace lifecycle.
438
- *
439
- * xmlXPathNodeSetDel() frees xmlNs structs, and so here we reproduce that
440
- * function with the xmlNs logic.
441
- */
442
- int i;
443
-
444
- if (cur == NULL) return;
445
- if (val == NULL) return;
446
-
447
- /*
448
- * find node in nodeTab
449
- */
450
- for (i = 0;i < cur->nodeNr;i++)
451
- if (cur->nodeTab[i] == val) break;
452
-
453
- if (i >= cur->nodeNr) { /* not found */
454
- return;
455
- }
456
- cur->nodeNr--;
457
- for (;i < cur->nodeNr;i++)
458
- cur->nodeTab[i] = cur->nodeTab[i + 1];
459
- cur->nodeTab[cur->nodeNr] = NULL;
490
+ xmlNodeSetPtr c_node_set;
491
+ TypedData_Get_Struct(rb_node_set, xmlNodeSet, &xml_node_set_type, c_node_set);
492
+ return c_node_set;
460
493
  }
461
494
 
462
495
 
463
- VALUE cNokogiriXmlNodeSet ;
464
- void init_xml_node_set(void)
496
+ void
497
+ noko_init_xml_node_set(void)
465
498
  {
466
- VALUE nokogiri = rb_define_module("Nokogiri");
467
- VALUE xml = rb_define_module_under(nokogiri, "XML");
468
- VALUE klass = rb_define_class_under(xml, "NodeSet", rb_cObject);
469
- cNokogiriXmlNodeSet = klass;
470
-
471
- rb_define_alloc_func(klass, allocate);
472
- rb_define_method(klass, "length", length, 0);
473
- rb_define_method(klass, "[]", slice, -1);
474
- rb_define_method(klass, "slice", slice, -1);
475
- rb_define_method(klass, "push", push, 1);
476
- rb_define_method(klass, "|", set_union, 1);
477
- rb_define_method(klass, "-", minus, 1);
478
- rb_define_method(klass, "unlink", unlink_nodeset, 0);
479
- rb_define_method(klass, "to_a", to_array, 0);
480
- rb_define_method(klass, "dup", duplicate, 0);
481
- rb_define_method(klass, "delete", delete, 1);
482
- rb_define_method(klass, "&", intersection, 1);
483
- rb_define_method(klass, "include?", include_eh, 1);
499
+ cNokogiriXmlNodeSet = rb_define_class_under(mNokogiriXml, "NodeSet", rb_cObject);
500
+
501
+ rb_define_alloc_func(cNokogiriXmlNodeSet, xml_node_set_allocate);
502
+
503
+ rb_define_method(cNokogiriXmlNodeSet, "&", intersection, 1);
504
+ rb_define_method(cNokogiriXmlNodeSet, "-", minus, 1);
505
+ rb_define_method(cNokogiriXmlNodeSet, "[]", slice, -1);
506
+ rb_define_method(cNokogiriXmlNodeSet, "delete", delete, 1);
507
+ rb_define_method(cNokogiriXmlNodeSet, "include?", include_eh, 1);
508
+ rb_define_method(cNokogiriXmlNodeSet, "length", length, 0);
509
+ rb_define_method(cNokogiriXmlNodeSet, "push", push, 1);
510
+ rb_define_method(cNokogiriXmlNodeSet, "slice", slice, -1);
511
+ rb_define_method(cNokogiriXmlNodeSet, "to_a", to_array, 0);
512
+ rb_define_method(cNokogiriXmlNodeSet, "unlink", unlink_nodeset, 0);
513
+ rb_define_method(cNokogiriXmlNodeSet, "|", rb_xml_node_set_union, 1);
514
+
515
+ rb_define_private_method(cNokogiriXmlNodeSet, "initialize_copy", rb_xml_node_set_initialize_copy, 1);
484
516
 
485
517
  decorate = rb_intern("decorate");
486
518
  }