nokogiri 1.6.2.rc1-x64-mingw32

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 (263) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +26 -0
  3. data/.editorconfig +17 -0
  4. data/.gemtest +0 -0
  5. data/.travis.yml +25 -0
  6. data/CHANGELOG.ja.rdoc +857 -0
  7. data/CHANGELOG.rdoc +880 -0
  8. data/C_CODING_STYLE.rdoc +33 -0
  9. data/Gemfile +21 -0
  10. data/Manifest.txt +371 -0
  11. data/README.ja.rdoc +112 -0
  12. data/README.rdoc +180 -0
  13. data/ROADMAP.md +89 -0
  14. data/Rakefile +351 -0
  15. data/STANDARD_RESPONSES.md +47 -0
  16. data/Y_U_NO_GEMSPEC.md +155 -0
  17. data/bin/nokogiri +78 -0
  18. data/build_all +130 -0
  19. data/dependencies.yml +4 -0
  20. data/ext/nokogiri/depend +358 -0
  21. data/ext/nokogiri/extconf.rb +453 -0
  22. data/ext/nokogiri/html_document.c +170 -0
  23. data/ext/nokogiri/html_document.h +10 -0
  24. data/ext/nokogiri/html_element_description.c +279 -0
  25. data/ext/nokogiri/html_element_description.h +10 -0
  26. data/ext/nokogiri/html_entity_lookup.c +32 -0
  27. data/ext/nokogiri/html_entity_lookup.h +8 -0
  28. data/ext/nokogiri/html_sax_parser_context.c +116 -0
  29. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  30. data/ext/nokogiri/html_sax_push_parser.c +87 -0
  31. data/ext/nokogiri/html_sax_push_parser.h +9 -0
  32. data/ext/nokogiri/nokogiri.c +148 -0
  33. data/ext/nokogiri/nokogiri.h +164 -0
  34. data/ext/nokogiri/xml_attr.c +94 -0
  35. data/ext/nokogiri/xml_attr.h +9 -0
  36. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  37. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  38. data/ext/nokogiri/xml_cdata.c +56 -0
  39. data/ext/nokogiri/xml_cdata.h +9 -0
  40. data/ext/nokogiri/xml_comment.c +54 -0
  41. data/ext/nokogiri/xml_comment.h +9 -0
  42. data/ext/nokogiri/xml_document.c +577 -0
  43. data/ext/nokogiri/xml_document.h +23 -0
  44. data/ext/nokogiri/xml_document_fragment.c +48 -0
  45. data/ext/nokogiri/xml_document_fragment.h +10 -0
  46. data/ext/nokogiri/xml_dtd.c +202 -0
  47. data/ext/nokogiri/xml_dtd.h +10 -0
  48. data/ext/nokogiri/xml_element_content.c +123 -0
  49. data/ext/nokogiri/xml_element_content.h +10 -0
  50. data/ext/nokogiri/xml_element_decl.c +69 -0
  51. data/ext/nokogiri/xml_element_decl.h +9 -0
  52. data/ext/nokogiri/xml_encoding_handler.c +79 -0
  53. data/ext/nokogiri/xml_encoding_handler.h +8 -0
  54. data/ext/nokogiri/xml_entity_decl.c +110 -0
  55. data/ext/nokogiri/xml_entity_decl.h +10 -0
  56. data/ext/nokogiri/xml_entity_reference.c +52 -0
  57. data/ext/nokogiri/xml_entity_reference.h +9 -0
  58. data/ext/nokogiri/xml_io.c +56 -0
  59. data/ext/nokogiri/xml_io.h +11 -0
  60. data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
  61. data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
  62. data/ext/nokogiri/xml_namespace.c +78 -0
  63. data/ext/nokogiri/xml_namespace.h +13 -0
  64. data/ext/nokogiri/xml_node.c +1541 -0
  65. data/ext/nokogiri/xml_node.h +13 -0
  66. data/ext/nokogiri/xml_node_set.c +467 -0
  67. data/ext/nokogiri/xml_node_set.h +14 -0
  68. data/ext/nokogiri/xml_processing_instruction.c +56 -0
  69. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  70. data/ext/nokogiri/xml_reader.c +681 -0
  71. data/ext/nokogiri/xml_reader.h +10 -0
  72. data/ext/nokogiri/xml_relax_ng.c +161 -0
  73. data/ext/nokogiri/xml_relax_ng.h +9 -0
  74. data/ext/nokogiri/xml_sax_parser.c +312 -0
  75. data/ext/nokogiri/xml_sax_parser.h +39 -0
  76. data/ext/nokogiri/xml_sax_parser_context.c +262 -0
  77. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  78. data/ext/nokogiri/xml_sax_push_parser.c +115 -0
  79. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  80. data/ext/nokogiri/xml_schema.c +205 -0
  81. data/ext/nokogiri/xml_schema.h +9 -0
  82. data/ext/nokogiri/xml_syntax_error.c +63 -0
  83. data/ext/nokogiri/xml_syntax_error.h +13 -0
  84. data/ext/nokogiri/xml_text.c +52 -0
  85. data/ext/nokogiri/xml_text.h +9 -0
  86. data/ext/nokogiri/xml_xpath_context.c +307 -0
  87. data/ext/nokogiri/xml_xpath_context.h +10 -0
  88. data/ext/nokogiri/xslt_stylesheet.c +270 -0
  89. data/ext/nokogiri/xslt_stylesheet.h +14 -0
  90. data/lib/nokogiri.rb +137 -0
  91. data/lib/nokogiri/2.0/nokogiri.so +0 -0
  92. data/lib/nokogiri/2.1/nokogiri.so +0 -0
  93. data/lib/nokogiri/css.rb +27 -0
  94. data/lib/nokogiri/css/node.rb +52 -0
  95. data/lib/nokogiri/css/parser.rb +715 -0
  96. data/lib/nokogiri/css/parser.y +249 -0
  97. data/lib/nokogiri/css/parser_extras.rb +91 -0
  98. data/lib/nokogiri/css/syntax_error.rb +7 -0
  99. data/lib/nokogiri/css/tokenizer.rb +152 -0
  100. data/lib/nokogiri/css/tokenizer.rex +55 -0
  101. data/lib/nokogiri/css/xpath_visitor.rb +219 -0
  102. data/lib/nokogiri/decorators/slop.rb +35 -0
  103. data/lib/nokogiri/html.rb +37 -0
  104. data/lib/nokogiri/html/builder.rb +35 -0
  105. data/lib/nokogiri/html/document.rb +333 -0
  106. data/lib/nokogiri/html/document_fragment.rb +41 -0
  107. data/lib/nokogiri/html/element_description.rb +23 -0
  108. data/lib/nokogiri/html/element_description_defaults.rb +671 -0
  109. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  110. data/lib/nokogiri/html/sax/parser.rb +52 -0
  111. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  112. data/lib/nokogiri/html/sax/push_parser.rb +16 -0
  113. data/lib/nokogiri/syntax_error.rb +4 -0
  114. data/lib/nokogiri/version.rb +106 -0
  115. data/lib/nokogiri/xml.rb +73 -0
  116. data/lib/nokogiri/xml/attr.rb +14 -0
  117. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  118. data/lib/nokogiri/xml/builder.rb +443 -0
  119. data/lib/nokogiri/xml/cdata.rb +11 -0
  120. data/lib/nokogiri/xml/character_data.rb +7 -0
  121. data/lib/nokogiri/xml/document.rb +279 -0
  122. data/lib/nokogiri/xml/document_fragment.rb +112 -0
  123. data/lib/nokogiri/xml/dtd.rb +32 -0
  124. data/lib/nokogiri/xml/element_content.rb +36 -0
  125. data/lib/nokogiri/xml/element_decl.rb +13 -0
  126. data/lib/nokogiri/xml/entity_decl.rb +19 -0
  127. data/lib/nokogiri/xml/namespace.rb +13 -0
  128. data/lib/nokogiri/xml/node.rb +982 -0
  129. data/lib/nokogiri/xml/node/save_options.rb +61 -0
  130. data/lib/nokogiri/xml/node_set.rb +355 -0
  131. data/lib/nokogiri/xml/notation.rb +6 -0
  132. data/lib/nokogiri/xml/parse_options.rb +98 -0
  133. data/lib/nokogiri/xml/pp.rb +2 -0
  134. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  135. data/lib/nokogiri/xml/pp/node.rb +56 -0
  136. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  137. data/lib/nokogiri/xml/reader.rb +112 -0
  138. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  139. data/lib/nokogiri/xml/sax.rb +4 -0
  140. data/lib/nokogiri/xml/sax/document.rb +171 -0
  141. data/lib/nokogiri/xml/sax/parser.rb +123 -0
  142. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  143. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  144. data/lib/nokogiri/xml/schema.rb +63 -0
  145. data/lib/nokogiri/xml/syntax_error.rb +47 -0
  146. data/lib/nokogiri/xml/text.rb +9 -0
  147. data/lib/nokogiri/xml/xpath.rb +10 -0
  148. data/lib/nokogiri/xml/xpath/syntax_error.rb +11 -0
  149. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  150. data/lib/nokogiri/xslt.rb +56 -0
  151. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  152. data/lib/xsd/xmlparser/nokogiri.rb +102 -0
  153. data/suppressions/README.txt +1 -0
  154. data/suppressions/nokogiri_ree-1.8.7.358.supp +61 -0
  155. data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
  156. data/suppressions/nokogiri_ruby-1.9.2.320.supp +28 -0
  157. data/suppressions/nokogiri_ruby-1.9.3.327.supp +28 -0
  158. data/tasks/nokogiri.org.rb +24 -0
  159. data/tasks/test.rb +95 -0
  160. data/test/css/test_nthiness.rb +222 -0
  161. data/test/css/test_parser.rb +358 -0
  162. data/test/css/test_tokenizer.rb +198 -0
  163. data/test/css/test_xpath_visitor.rb +96 -0
  164. data/test/decorators/test_slop.rb +16 -0
  165. data/test/files/2ch.html +108 -0
  166. data/test/files/address_book.rlx +12 -0
  167. data/test/files/address_book.xml +10 -0
  168. data/test/files/atom.xml +344 -0
  169. data/test/files/bar/bar.xsd +4 -0
  170. data/test/files/bogus.xml +0 -0
  171. data/test/files/dont_hurt_em_why.xml +422 -0
  172. data/test/files/encoding.html +82 -0
  173. data/test/files/encoding.xhtml +84 -0
  174. data/test/files/exslt.xml +8 -0
  175. data/test/files/exslt.xslt +35 -0
  176. data/test/files/foo/foo.xsd +4 -0
  177. data/test/files/metacharset.html +10 -0
  178. data/test/files/noencoding.html +47 -0
  179. data/test/files/po.xml +32 -0
  180. data/test/files/po.xsd +66 -0
  181. data/test/files/saml/saml20assertion_schema.xsd +283 -0
  182. data/test/files/saml/saml20protocol_schema.xsd +302 -0
  183. data/test/files/saml/xenc_schema.xsd +146 -0
  184. data/test/files/saml/xmldsig_schema.xsd +318 -0
  185. data/test/files/shift_jis.html +10 -0
  186. data/test/files/shift_jis.xml +5 -0
  187. data/test/files/shift_jis_no_charset.html +9 -0
  188. data/test/files/snuggles.xml +3 -0
  189. data/test/files/staff.dtd +10 -0
  190. data/test/files/staff.xml +59 -0
  191. data/test/files/staff.xslt +32 -0
  192. data/test/files/test_document_url/bar.xml +2 -0
  193. data/test/files/test_document_url/document.dtd +4 -0
  194. data/test/files/test_document_url/document.xml +6 -0
  195. data/test/files/tlm.html +850 -0
  196. data/test/files/to_be_xincluded.xml +2 -0
  197. data/test/files/valid_bar.xml +2 -0
  198. data/test/files/xinclude.xml +4 -0
  199. data/test/helper.rb +164 -0
  200. data/test/html/sax/test_parser.rb +141 -0
  201. data/test/html/sax/test_parser_context.rb +46 -0
  202. data/test/html/test_builder.rb +164 -0
  203. data/test/html/test_document.rb +619 -0
  204. data/test/html/test_document_encoding.rb +148 -0
  205. data/test/html/test_document_fragment.rb +261 -0
  206. data/test/html/test_element_description.rb +105 -0
  207. data/test/html/test_named_characters.rb +14 -0
  208. data/test/html/test_node.rb +196 -0
  209. data/test/html/test_node_encoding.rb +27 -0
  210. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +14 -0
  211. data/test/namespaces/test_namespaces_in_builder_doc.rb +75 -0
  212. data/test/namespaces/test_namespaces_in_cloned_doc.rb +31 -0
  213. data/test/namespaces/test_namespaces_in_created_doc.rb +75 -0
  214. data/test/namespaces/test_namespaces_in_parsed_doc.rb +66 -0
  215. data/test/test_convert_xpath.rb +135 -0
  216. data/test/test_css_cache.rb +45 -0
  217. data/test/test_encoding_handler.rb +46 -0
  218. data/test/test_memory_leak.rb +156 -0
  219. data/test/test_nokogiri.rb +138 -0
  220. data/test/test_reader.rb +558 -0
  221. data/test/test_soap4r_sax.rb +52 -0
  222. data/test/test_xslt_transforms.rb +279 -0
  223. data/test/xml/node/test_save_options.rb +28 -0
  224. data/test/xml/node/test_subclass.rb +44 -0
  225. data/test/xml/sax/test_parser.rb +382 -0
  226. data/test/xml/sax/test_parser_context.rb +115 -0
  227. data/test/xml/sax/test_push_parser.rb +157 -0
  228. data/test/xml/test_attr.rb +64 -0
  229. data/test/xml/test_attribute_decl.rb +86 -0
  230. data/test/xml/test_builder.rb +315 -0
  231. data/test/xml/test_c14n.rb +161 -0
  232. data/test/xml/test_cdata.rb +48 -0
  233. data/test/xml/test_comment.rb +29 -0
  234. data/test/xml/test_document.rb +934 -0
  235. data/test/xml/test_document_encoding.rb +28 -0
  236. data/test/xml/test_document_fragment.rb +228 -0
  237. data/test/xml/test_dtd.rb +187 -0
  238. data/test/xml/test_dtd_encoding.rb +33 -0
  239. data/test/xml/test_element_content.rb +56 -0
  240. data/test/xml/test_element_decl.rb +73 -0
  241. data/test/xml/test_entity_decl.rb +122 -0
  242. data/test/xml/test_entity_reference.rb +245 -0
  243. data/test/xml/test_namespace.rb +95 -0
  244. data/test/xml/test_node.rb +1155 -0
  245. data/test/xml/test_node_attributes.rb +113 -0
  246. data/test/xml/test_node_encoding.rb +107 -0
  247. data/test/xml/test_node_inheritance.rb +32 -0
  248. data/test/xml/test_node_reparenting.rb +374 -0
  249. data/test/xml/test_node_set.rb +755 -0
  250. data/test/xml/test_parse_options.rb +64 -0
  251. data/test/xml/test_processing_instruction.rb +30 -0
  252. data/test/xml/test_reader_encoding.rb +142 -0
  253. data/test/xml/test_relax_ng.rb +60 -0
  254. data/test/xml/test_schema.rb +129 -0
  255. data/test/xml/test_syntax_error.rb +12 -0
  256. data/test/xml/test_text.rb +45 -0
  257. data/test/xml/test_unparented_node.rb +422 -0
  258. data/test/xml/test_xinclude.rb +83 -0
  259. data/test/xml/test_xpath.rb +376 -0
  260. data/test/xslt/test_custom_functions.rb +133 -0
  261. data/test/xslt/test_exception_handling.rb +37 -0
  262. data/test_all +81 -0
  263. metadata +601 -0
@@ -0,0 +1,13 @@
1
+ #ifndef NOKOGIRI_XML_NODE
2
+ #define NOKOGIRI_XML_NODE
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_node();
7
+
8
+ extern VALUE cNokogiriXmlNode ;
9
+ extern VALUE cNokogiriXmlElement ;
10
+
11
+ VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node) ;
12
+ void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_hash) ;
13
+ #endif
@@ -0,0 +1,467 @@
1
+ #include <xml_node_set.h>
2
+ #include <libxml/xpathInternals.h>
3
+
4
+ static ID decorate ;
5
+
6
+ static int dealloc_namespace(xmlNsPtr ns)
7
+ {
8
+ if (ns->href)
9
+ xmlFree((xmlChar *)ns->href);
10
+ if (ns->prefix)
11
+ xmlFree((xmlChar *)ns->prefix);
12
+ xmlFree(ns);
13
+ return ST_CONTINUE;
14
+ }
15
+
16
+ static void deallocate(nokogiriNodeSetTuple *tuple)
17
+ {
18
+ /*
19
+ * xmlXPathFreeNodeSet() contains an implicit assumption that it is being
20
+ * called before any of its pointed-to nodes have been free()d. this
21
+ * assumption lies in the operation where it dereferences nodeTab pointers
22
+ * while searching for namespace nodes to free.
23
+ *
24
+ * however, since Ruby's GC mechanism cannot guarantee the strict order in
25
+ * which ruby objects will be GC'd, nodes may be garbage collected before a
26
+ * nodeset containing pointers to those nodes. (this is true regardless of
27
+ * how we declare dependencies between objects with rb_gc_mark().)
28
+ *
29
+ * as a result, xmlXPathFreeNodeSet() will perform unsafe memory operations,
30
+ * and calling it would be evil.
31
+ *
32
+ * so here, we *manually* free the set of namespace nodes that was
33
+ * constructed at initialization time (see Nokogiri_wrap_xml_node_set()), as
34
+ * well as the NodeSet, without using the official xmlXPathFreeNodeSet().
35
+ *
36
+ * there's probably a lesson in here somewhere about intermingling, within a
37
+ * single array, structs with different memory-ownership semantics. or more
38
+ * generally, a lesson about building an API in C/C++ that does not contain
39
+ * assumptions about the strict order in which memory will be released. hey,
40
+ * that sounds like a great idea for a blog post! get to it!
41
+ *
42
+ * "In Valgrind We Trust." seriously.
43
+ */
44
+ xmlNodeSetPtr node_set;
45
+
46
+ node_set = tuple->node_set;
47
+
48
+ if (!node_set)
49
+ return;
50
+
51
+ NOKOGIRI_DEBUG_START(node_set) ;
52
+ st_foreach(tuple->namespaces, dealloc_namespace, 0);
53
+
54
+ if (node_set->nodeTab != NULL)
55
+ xmlFree(node_set->nodeTab);
56
+
57
+ xmlFree(node_set);
58
+ st_free_table(tuple->namespaces);
59
+ free(tuple);
60
+ NOKOGIRI_DEBUG_END(node_set) ;
61
+ }
62
+
63
+ static VALUE allocate(VALUE klass)
64
+ {
65
+ return Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL), Qnil);
66
+ }
67
+
68
+
69
+ /*
70
+ * call-seq:
71
+ * dup
72
+ *
73
+ * Duplicate this node set
74
+ */
75
+ static VALUE duplicate(VALUE self)
76
+ {
77
+ nokogiriNodeSetTuple *tuple;
78
+ xmlNodeSetPtr dupl;
79
+
80
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
81
+
82
+ dupl = xmlXPathNodeSetMerge(NULL, tuple->node_set);
83
+
84
+ return Nokogiri_wrap_xml_node_set(dupl, rb_iv_get(self, "@document"));
85
+ }
86
+
87
+ /*
88
+ * call-seq:
89
+ * length
90
+ *
91
+ * Get the length of the node set
92
+ */
93
+ static VALUE length(VALUE self)
94
+ {
95
+ nokogiriNodeSetTuple *tuple;
96
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
97
+
98
+ return tuple->node_set ? INT2NUM(tuple->node_set->nodeNr) : INT2NUM(0);
99
+ }
100
+
101
+ /*
102
+ * call-seq:
103
+ * push(node)
104
+ *
105
+ * Append +node+ to the NodeSet.
106
+ */
107
+ static VALUE push(VALUE self, VALUE rb_node)
108
+ {
109
+ nokogiriNodeSetTuple *tuple;
110
+ xmlNodePtr node;
111
+
112
+ if(!(rb_obj_is_kind_of(rb_node, cNokogiriXmlNode) || rb_obj_is_kind_of(rb_node, cNokogiriXmlNamespace)))
113
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node or Nokogiri::XML::Namespace");
114
+
115
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
116
+ Data_Get_Struct(rb_node, xmlNode, node);
117
+ xmlXPathNodeSetAdd(tuple->node_set, node);
118
+ return self;
119
+ }
120
+
121
+ /*
122
+ * call-seq:
123
+ * delete(node)
124
+ *
125
+ * Delete +node+ from the Nodeset, if it is a member. Returns the deleted node
126
+ * if found, otherwise returns nil.
127
+ */
128
+ static VALUE
129
+ delete(VALUE self, VALUE rb_node)
130
+ {
131
+ nokogiriNodeSetTuple *tuple;
132
+ xmlNodePtr node;
133
+ xmlNodeSetPtr cur;
134
+ int i;
135
+
136
+ if (!(rb_obj_is_kind_of(rb_node, cNokogiriXmlNode) || rb_obj_is_kind_of(rb_node, cNokogiriXmlNamespace)))
137
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node or Nokogiri::XML::Namespace");
138
+
139
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
140
+ Data_Get_Struct(rb_node, xmlNode, node);
141
+ cur = tuple->node_set;
142
+
143
+ if (xmlXPathNodeSetContains(cur, node)) {
144
+ for (i = 0; i < cur->nodeNr; i++)
145
+ if (cur->nodeTab[i] == node) break;
146
+
147
+ cur->nodeNr--;
148
+ for (;i < cur->nodeNr;i++)
149
+ cur->nodeTab[i] = cur->nodeTab[i + 1];
150
+ cur->nodeTab[cur->nodeNr] = NULL;
151
+ return rb_node;
152
+ }
153
+ return Qnil ;
154
+ }
155
+
156
+
157
+ /*
158
+ * call-seq:
159
+ * &(node_set)
160
+ *
161
+ * Set Intersection — Returns a new NodeSet containing nodes common to the two NodeSets.
162
+ */
163
+ static VALUE intersection(VALUE self, VALUE rb_other)
164
+ {
165
+ nokogiriNodeSetTuple *tuple, *other;
166
+ xmlNodeSetPtr intersection;
167
+
168
+ if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
169
+ rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
170
+
171
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
172
+ Data_Get_Struct(rb_other, nokogiriNodeSetTuple, other);
173
+
174
+ intersection = xmlXPathIntersection(tuple->node_set, other->node_set);
175
+ return Nokogiri_wrap_xml_node_set(intersection, rb_iv_get(self, "@document"));
176
+ }
177
+
178
+
179
+ /*
180
+ * call-seq:
181
+ * include?(node)
182
+ *
183
+ * Returns true if any member of node set equals +node+.
184
+ */
185
+ static VALUE include_eh(VALUE self, VALUE rb_node)
186
+ {
187
+ nokogiriNodeSetTuple *tuple;
188
+ xmlNodePtr node;
189
+
190
+ if(!(rb_obj_is_kind_of(rb_node, cNokogiriXmlNode) || rb_obj_is_kind_of(rb_node, cNokogiriXmlNamespace)))
191
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node or Nokogiri::XML::Namespace");
192
+
193
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
194
+ Data_Get_Struct(rb_node, xmlNode, node);
195
+
196
+ return (xmlXPathNodeSetContains(tuple->node_set, node) ? Qtrue : Qfalse);
197
+ }
198
+
199
+
200
+ /*
201
+ * call-seq:
202
+ * |(node_set)
203
+ *
204
+ * Returns a new set built by merging the set and the elements of the given
205
+ * set.
206
+ */
207
+ static VALUE set_union(VALUE self, VALUE rb_other)
208
+ {
209
+ nokogiriNodeSetTuple *tuple, *other;
210
+ xmlNodeSetPtr new;
211
+
212
+ if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
213
+ rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
214
+
215
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
216
+ Data_Get_Struct(rb_other, nokogiriNodeSetTuple, other);
217
+
218
+ new = xmlXPathNodeSetMerge(NULL, tuple->node_set);
219
+ new = xmlXPathNodeSetMerge(new, other->node_set);
220
+
221
+ return Nokogiri_wrap_xml_node_set(new, rb_iv_get(self, "@document"));
222
+ }
223
+
224
+ /*
225
+ * call-seq:
226
+ * -(node_set)
227
+ *
228
+ * Difference - returns a new NodeSet that is a copy of this NodeSet, removing
229
+ * each item that also appears in +node_set+
230
+ */
231
+ static VALUE minus(VALUE self, VALUE rb_other)
232
+ {
233
+ nokogiriNodeSetTuple *tuple, *other;
234
+ xmlNodeSetPtr new;
235
+ int j ;
236
+
237
+ if(!rb_obj_is_kind_of(rb_other, cNokogiriXmlNodeSet))
238
+ rb_raise(rb_eArgError, "node_set must be a Nokogiri::XML::NodeSet");
239
+
240
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
241
+ Data_Get_Struct(rb_other, nokogiriNodeSetTuple, other);
242
+
243
+ new = xmlXPathNodeSetMerge(NULL, tuple->node_set);
244
+ for (j = 0 ; j < other->node_set->nodeNr ; ++j) {
245
+ xmlXPathNodeSetDel(new, other->node_set->nodeTab[j]);
246
+ }
247
+
248
+ return Nokogiri_wrap_xml_node_set(new, rb_iv_get(self, "@document"));
249
+ }
250
+
251
+
252
+ static VALUE index_at(VALUE self, long offset)
253
+ {
254
+ xmlNodeSetPtr node_set;
255
+ nokogiriNodeSetTuple *tuple;
256
+
257
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
258
+ node_set = tuple->node_set;
259
+
260
+ if (offset >= node_set->nodeNr || abs((int)offset) > node_set->nodeNr)
261
+ return Qnil;
262
+
263
+ if (offset < 0)
264
+ offset += node_set->nodeNr;
265
+
266
+ if (XML_NAMESPACE_DECL == node_set->nodeTab[offset]->type)
267
+ return Nokogiri_wrap_xml_namespace2(rb_iv_get(self, "@document"), (xmlNsPtr)(node_set->nodeTab[offset]));
268
+ return Nokogiri_wrap_xml_node(Qnil, node_set->nodeTab[offset]);
269
+ }
270
+
271
+ static VALUE subseq(VALUE self, long beg, long len)
272
+ {
273
+ long j;
274
+ nokogiriNodeSetTuple *tuple;
275
+ xmlNodeSetPtr node_set;
276
+ xmlNodeSetPtr new_set ;
277
+
278
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
279
+ node_set = tuple->node_set;
280
+
281
+ if (beg > node_set->nodeNr) return Qnil ;
282
+ if (beg < 0 || len < 0) return Qnil ;
283
+
284
+ if ((beg + len) > node_set->nodeNr) {
285
+ len = node_set->nodeNr - beg ;
286
+ }
287
+
288
+ new_set = xmlXPathNodeSetCreate(NULL);
289
+ for (j = beg ; j < beg+len ; ++j) {
290
+ xmlXPathNodeSetAddUnique(new_set, node_set->nodeTab[j]);
291
+ }
292
+ return Nokogiri_wrap_xml_node_set(new_set, rb_iv_get(self, "@document"));
293
+ }
294
+
295
+ /*
296
+ * call-seq:
297
+ * [index] -> Node or nil
298
+ * [start, length] -> NodeSet or nil
299
+ * [range] -> NodeSet or nil
300
+ * slice(index) -> Node or nil
301
+ * slice(start, length) -> NodeSet or nil
302
+ * slice(range) -> NodeSet or nil
303
+ *
304
+ * Element reference - returns the node at +index+, or returns a NodeSet
305
+ * containing nodes starting at +start+ and continuing for +length+ elements, or
306
+ * returns a NodeSet containing nodes specified by +range+. Negative +indices+
307
+ * count backward from the end of the +node_set+ (-1 is the last node). Returns
308
+ * nil if the +index+ (or +start+) are out of range.
309
+ */
310
+ static VALUE slice(int argc, VALUE *argv, VALUE self)
311
+ {
312
+ VALUE arg ;
313
+ long beg, len ;
314
+ xmlNodeSetPtr node_set;
315
+ nokogiriNodeSetTuple *tuple;
316
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
317
+ node_set = tuple->node_set;
318
+
319
+ if (argc == 2) {
320
+ beg = NUM2LONG(argv[0]);
321
+ len = NUM2LONG(argv[1]);
322
+ if (beg < 0) {
323
+ beg += node_set->nodeNr ;
324
+ }
325
+ return subseq(self, beg, len);
326
+ }
327
+
328
+ if (argc != 1) {
329
+ rb_scan_args(argc, argv, "11", NULL, NULL);
330
+ }
331
+ arg = argv[0];
332
+
333
+ if (FIXNUM_P(arg)) {
334
+ return index_at(self, FIX2LONG(arg));
335
+ }
336
+
337
+ /* if arg is Range */
338
+ switch (rb_range_beg_len(arg, &beg, &len, (long)node_set->nodeNr, 0)) {
339
+ case Qfalse:
340
+ break;
341
+ case Qnil:
342
+ return Qnil;
343
+ default:
344
+ return subseq(self, beg, len);
345
+ }
346
+
347
+ return index_at(self, NUM2LONG(arg));
348
+ }
349
+
350
+
351
+ /*
352
+ * call-seq:
353
+ * to_a
354
+ *
355
+ * Return this list as an Array
356
+ */
357
+ static VALUE to_array(VALUE self, VALUE rb_node)
358
+ {
359
+ xmlNodeSetPtr set;
360
+ VALUE *elts;
361
+ VALUE list;
362
+ int i;
363
+ nokogiriNodeSetTuple *tuple;
364
+
365
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
366
+ set = tuple->node_set;
367
+
368
+ elts = calloc((size_t)set->nodeNr, sizeof(VALUE *));
369
+ for(i = 0; i < set->nodeNr; i++) {
370
+ if (XML_NAMESPACE_DECL == set->nodeTab[i]->type)
371
+ elts[i] = Nokogiri_wrap_xml_namespace2(rb_iv_get(self, "@document"), (xmlNsPtr)(set->nodeTab[i]));
372
+ else
373
+ elts[i] = Nokogiri_wrap_xml_node(Qnil, set->nodeTab[i]);
374
+ }
375
+
376
+ list = rb_ary_new4((long)set->nodeNr, elts);
377
+
378
+ /*free(elts); */
379
+
380
+ return list;
381
+ }
382
+
383
+ /*
384
+ * call-seq:
385
+ * unlink
386
+ *
387
+ * Unlink this NodeSet and all Node objects it contains from their current context.
388
+ */
389
+ static VALUE unlink_nodeset(VALUE self)
390
+ {
391
+ xmlNodeSetPtr node_set;
392
+ int j, nodeNr ;
393
+ nokogiriNodeSetTuple *tuple;
394
+
395
+ Data_Get_Struct(self, nokogiriNodeSetTuple, tuple);
396
+ node_set = tuple->node_set;
397
+ nodeNr = node_set->nodeNr ;
398
+ for (j = 0 ; j < nodeNr ; j++) {
399
+ if (XML_NAMESPACE_DECL != node_set->nodeTab[j]->type) {
400
+ VALUE node ;
401
+ xmlNodePtr node_ptr;
402
+ node = Nokogiri_wrap_xml_node(Qnil, node_set->nodeTab[j]);
403
+ rb_funcall(node, rb_intern("unlink"), 0); /* modifies the C struct out from under the object */
404
+ Data_Get_Struct(node, xmlNode, node_ptr);
405
+ node_set->nodeTab[j] = node_ptr ;
406
+ }
407
+ }
408
+ return self ;
409
+ }
410
+
411
+ VALUE Nokogiri_wrap_xml_node_set(xmlNodeSetPtr node_set, VALUE document)
412
+ {
413
+ VALUE new_set ;
414
+ int i;
415
+ xmlNodePtr cur;
416
+ xmlNsPtr ns;
417
+ nokogiriNodeSetTuple *tuple;
418
+
419
+ new_set = Data_Make_Struct(cNokogiriXmlNodeSet, nokogiriNodeSetTuple, 0,
420
+ deallocate, tuple);
421
+
422
+ tuple->node_set = node_set;
423
+ tuple->namespaces = st_init_numtable();
424
+
425
+ if (!NIL_P(document)) {
426
+ rb_iv_set(new_set, "@document", document);
427
+ rb_funcall(document, decorate, 1, new_set);
428
+ }
429
+
430
+ if (node_set && node_set->nodeTab) {
431
+ for (i = 0; i < node_set->nodeNr; i++) {
432
+ cur = node_set->nodeTab[i];
433
+ if (cur && cur->type == XML_NAMESPACE_DECL) {
434
+ ns = (xmlNsPtr)cur;
435
+ if (ns->next && ns->next->type != XML_NAMESPACE_DECL)
436
+ st_insert(tuple->namespaces, (st_data_t)cur, (st_data_t)0);
437
+ }
438
+ }
439
+ }
440
+
441
+ return new_set ;
442
+ }
443
+
444
+ VALUE cNokogiriXmlNodeSet ;
445
+ void init_xml_node_set(void)
446
+ {
447
+ VALUE nokogiri = rb_define_module("Nokogiri");
448
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
449
+ VALUE klass = rb_define_class_under(xml, "NodeSet", rb_cObject);
450
+ cNokogiriXmlNodeSet = klass;
451
+
452
+ rb_define_alloc_func(klass, allocate);
453
+ rb_define_method(klass, "length", length, 0);
454
+ rb_define_method(klass, "[]", slice, -1);
455
+ rb_define_method(klass, "slice", slice, -1);
456
+ rb_define_method(klass, "push", push, 1);
457
+ rb_define_method(klass, "|", set_union, 1);
458
+ rb_define_method(klass, "-", minus, 1);
459
+ rb_define_method(klass, "unlink", unlink_nodeset, 0);
460
+ rb_define_method(klass, "to_a", to_array, 0);
461
+ rb_define_method(klass, "dup", duplicate, 0);
462
+ rb_define_method(klass, "delete", delete, 1);
463
+ rb_define_method(klass, "&", intersection, 1);
464
+ rb_define_method(klass, "include?", include_eh, 1);
465
+
466
+ decorate = rb_intern("decorate");
467
+ }