nokogiri 1.0.0 → 1.6.8.1

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 (309) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +26 -0
  3. data/.cross_rubies +9 -0
  4. data/.editorconfig +17 -0
  5. data/.gemtest +0 -0
  6. data/.travis.yml +51 -0
  7. data/CHANGELOG.rdoc +1160 -0
  8. data/CONTRIBUTING.md +42 -0
  9. data/C_CODING_STYLE.rdoc +33 -0
  10. data/Gemfile +22 -0
  11. data/LICENSE.txt +31 -0
  12. data/Manifest.txt +284 -40
  13. data/README.md +166 -0
  14. data/ROADMAP.md +111 -0
  15. data/Rakefile +310 -199
  16. data/STANDARD_RESPONSES.md +47 -0
  17. data/Y_U_NO_GEMSPEC.md +155 -0
  18. data/appveyor.yml +22 -0
  19. data/bin/nokogiri +118 -0
  20. data/build_all +45 -0
  21. data/dependencies.yml +29 -0
  22. data/ext/nokogiri/depend +358 -0
  23. data/ext/nokogiri/extconf.rb +664 -34
  24. data/ext/nokogiri/html_document.c +120 -33
  25. data/ext/nokogiri/html_document.h +1 -1
  26. data/ext/nokogiri/html_element_description.c +279 -0
  27. data/ext/nokogiri/html_element_description.h +10 -0
  28. data/ext/nokogiri/html_entity_lookup.c +32 -0
  29. data/ext/nokogiri/html_entity_lookup.h +8 -0
  30. data/ext/nokogiri/html_sax_parser_context.c +116 -0
  31. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  32. data/ext/nokogiri/html_sax_push_parser.c +87 -0
  33. data/ext/nokogiri/html_sax_push_parser.h +9 -0
  34. data/ext/nokogiri/nokogiri.c +145 -0
  35. data/ext/nokogiri/nokogiri.h +131 -0
  36. data/ext/nokogiri/xml_attr.c +94 -0
  37. data/ext/nokogiri/xml_attr.h +9 -0
  38. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  39. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  40. data/ext/nokogiri/xml_cdata.c +23 -19
  41. data/ext/nokogiri/xml_cdata.h +1 -1
  42. data/ext/nokogiri/xml_comment.c +69 -0
  43. data/ext/nokogiri/xml_comment.h +9 -0
  44. data/ext/nokogiri/xml_document.c +501 -54
  45. data/ext/nokogiri/xml_document.h +14 -1
  46. data/ext/nokogiri/xml_document_fragment.c +48 -0
  47. data/ext/nokogiri/xml_document_fragment.h +10 -0
  48. data/ext/nokogiri/xml_dtd.c +109 -24
  49. data/ext/nokogiri/xml_dtd.h +3 -1
  50. data/ext/nokogiri/xml_element_content.c +123 -0
  51. data/ext/nokogiri/xml_element_content.h +10 -0
  52. data/ext/nokogiri/xml_element_decl.c +69 -0
  53. data/ext/nokogiri/xml_element_decl.h +9 -0
  54. data/ext/nokogiri/xml_encoding_handler.c +79 -0
  55. data/ext/nokogiri/xml_encoding_handler.h +8 -0
  56. data/ext/nokogiri/xml_entity_decl.c +110 -0
  57. data/ext/nokogiri/xml_entity_decl.h +10 -0
  58. data/ext/nokogiri/xml_entity_reference.c +52 -0
  59. data/ext/nokogiri/xml_entity_reference.h +9 -0
  60. data/ext/nokogiri/xml_io.c +60 -0
  61. data/ext/nokogiri/xml_io.h +11 -0
  62. data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
  63. data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
  64. data/ext/nokogiri/xml_namespace.c +117 -0
  65. data/ext/nokogiri/xml_namespace.h +13 -0
  66. data/ext/nokogiri/xml_node.c +1285 -315
  67. data/ext/nokogiri/xml_node.h +4 -6
  68. data/ext/nokogiri/xml_node_set.c +415 -54
  69. data/ext/nokogiri/xml_node_set.h +6 -2
  70. data/ext/nokogiri/xml_processing_instruction.c +56 -0
  71. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  72. data/ext/nokogiri/xml_reader.c +316 -77
  73. data/ext/nokogiri/xml_reader.h +1 -1
  74. data/ext/nokogiri/xml_relax_ng.c +161 -0
  75. data/ext/nokogiri/xml_relax_ng.h +9 -0
  76. data/ext/nokogiri/xml_sax_parser.c +215 -80
  77. data/ext/nokogiri/xml_sax_parser.h +30 -1
  78. data/ext/nokogiri/xml_sax_parser_context.c +262 -0
  79. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  80. data/ext/nokogiri/xml_sax_push_parser.c +115 -0
  81. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  82. data/ext/nokogiri/xml_schema.c +205 -0
  83. data/ext/nokogiri/xml_schema.h +9 -0
  84. data/ext/nokogiri/xml_syntax_error.c +45 -175
  85. data/ext/nokogiri/xml_syntax_error.h +4 -2
  86. data/ext/nokogiri/xml_text.c +37 -14
  87. data/ext/nokogiri/xml_text.h +1 -1
  88. data/ext/nokogiri/xml_xpath_context.c +230 -13
  89. data/ext/nokogiri/xml_xpath_context.h +2 -1
  90. data/ext/nokogiri/xslt_stylesheet.c +196 -34
  91. data/ext/nokogiri/xslt_stylesheet.h +6 -1
  92. data/lib/nokogiri/css/node.rb +18 -61
  93. data/lib/nokogiri/css/parser.rb +725 -17
  94. data/lib/nokogiri/css/parser.y +126 -63
  95. data/lib/nokogiri/css/parser_extras.rb +91 -0
  96. data/lib/nokogiri/css/syntax_error.rb +7 -0
  97. data/lib/nokogiri/css/tokenizer.rb +148 -5
  98. data/lib/nokogiri/css/tokenizer.rex +31 -39
  99. data/lib/nokogiri/css/xpath_visitor.rb +109 -51
  100. data/lib/nokogiri/css.rb +24 -3
  101. data/lib/nokogiri/decorators/slop.rb +42 -0
  102. data/lib/nokogiri/html/builder.rb +27 -1
  103. data/lib/nokogiri/html/document.rb +329 -3
  104. data/lib/nokogiri/html/document_fragment.rb +39 -0
  105. data/lib/nokogiri/html/element_description.rb +23 -0
  106. data/lib/nokogiri/html/element_description_defaults.rb +671 -0
  107. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  108. data/lib/nokogiri/html/sax/parser.rb +35 -4
  109. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  110. data/lib/nokogiri/html/sax/push_parser.rb +36 -0
  111. data/lib/nokogiri/html.rb +18 -76
  112. data/lib/nokogiri/syntax_error.rb +4 -0
  113. data/lib/nokogiri/version.rb +106 -1
  114. data/lib/nokogiri/xml/attr.rb +14 -0
  115. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  116. data/lib/nokogiri/xml/builder.rb +395 -31
  117. data/lib/nokogiri/xml/cdata.rb +4 -2
  118. data/lib/nokogiri/xml/character_data.rb +7 -0
  119. data/lib/nokogiri/xml/document.rb +267 -12
  120. data/lib/nokogiri/xml/document_fragment.rb +149 -0
  121. data/lib/nokogiri/xml/dtd.rb +27 -1
  122. data/lib/nokogiri/xml/element_content.rb +36 -0
  123. data/lib/nokogiri/xml/element_decl.rb +13 -0
  124. data/lib/nokogiri/xml/entity_decl.rb +19 -0
  125. data/lib/nokogiri/xml/namespace.rb +13 -0
  126. data/lib/nokogiri/xml/node/save_options.rb +61 -0
  127. data/lib/nokogiri/xml/node.rb +748 -109
  128. data/lib/nokogiri/xml/node_set.rb +200 -72
  129. data/lib/nokogiri/xml/parse_options.rb +120 -0
  130. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  131. data/lib/nokogiri/xml/pp/node.rb +56 -0
  132. data/lib/nokogiri/xml/pp.rb +2 -0
  133. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  134. data/lib/nokogiri/xml/reader.rb +102 -4
  135. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  136. data/lib/nokogiri/xml/sax/document.rb +114 -2
  137. data/lib/nokogiri/xml/sax/parser.rb +97 -7
  138. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  139. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  140. data/lib/nokogiri/xml/sax.rb +2 -7
  141. data/lib/nokogiri/xml/schema.rb +63 -0
  142. data/lib/nokogiri/xml/searchable.rb +221 -0
  143. data/lib/nokogiri/xml/syntax_error.rb +27 -1
  144. data/lib/nokogiri/xml/text.rb +4 -1
  145. data/lib/nokogiri/xml/xpath/syntax_error.rb +11 -0
  146. data/lib/nokogiri/xml/xpath.rb +4 -0
  147. data/lib/nokogiri/xml/xpath_context.rb +3 -1
  148. data/lib/nokogiri/xml.rb +45 -38
  149. data/lib/nokogiri/xslt/stylesheet.rb +19 -0
  150. data/lib/nokogiri/xslt.rb +47 -2
  151. data/lib/nokogiri.rb +117 -24
  152. data/lib/xsd/xmlparser/nokogiri.rb +102 -0
  153. data/patches/sort-patches-by-date +25 -0
  154. data/ports/archives/libxml2-2.9.4.tar.gz +0 -0
  155. data/ports/archives/libxslt-1.1.29.tar.gz +0 -0
  156. data/suppressions/README.txt +1 -0
  157. data/suppressions/nokogiri_ree-1.8.7.358.supp +61 -0
  158. data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
  159. data/suppressions/nokogiri_ruby-1.9.2.320.supp +28 -0
  160. data/suppressions/nokogiri_ruby-1.9.3.327.supp +28 -0
  161. data/tasks/test.rb +100 -0
  162. data/test/css/test_nthiness.rb +73 -6
  163. data/test/css/test_parser.rb +184 -39
  164. data/test/css/test_tokenizer.rb +72 -19
  165. data/test/css/test_xpath_visitor.rb +44 -2
  166. data/test/decorators/test_slop.rb +20 -0
  167. data/test/files/2ch.html +108 -0
  168. data/test/files/GH_1042.html +18 -0
  169. data/test/files/address_book.rlx +12 -0
  170. data/test/files/address_book.xml +10 -0
  171. data/test/files/atom.xml +344 -0
  172. data/test/files/bar/bar.xsd +4 -0
  173. data/test/files/bogus.xml +0 -0
  174. data/test/files/dont_hurt_em_why.xml +422 -0
  175. data/test/files/encoding.html +82 -0
  176. data/test/files/encoding.xhtml +84 -0
  177. data/test/files/exslt.xml +8 -0
  178. data/test/files/exslt.xslt +35 -0
  179. data/test/files/foo/foo.xsd +4 -0
  180. data/test/files/metacharset.html +10 -0
  181. data/test/files/namespace_pressure_test.xml +1684 -0
  182. data/test/files/noencoding.html +47 -0
  183. data/test/files/po.xml +32 -0
  184. data/test/files/po.xsd +66 -0
  185. data/test/files/saml/saml20assertion_schema.xsd +283 -0
  186. data/test/files/saml/saml20protocol_schema.xsd +302 -0
  187. data/test/files/saml/xenc_schema.xsd +146 -0
  188. data/test/files/saml/xmldsig_schema.xsd +318 -0
  189. data/test/files/shift_jis.html +10 -0
  190. data/test/files/shift_jis.xml +5 -0
  191. data/test/files/shift_jis_no_charset.html +9 -0
  192. data/test/files/slow-xpath.xml +25509 -0
  193. data/test/files/snuggles.xml +3 -0
  194. data/test/files/staff.dtd +10 -0
  195. data/test/files/test_document_url/bar.xml +2 -0
  196. data/test/files/test_document_url/document.dtd +4 -0
  197. data/test/files/test_document_url/document.xml +6 -0
  198. data/test/files/tlm.html +2 -1
  199. data/test/files/to_be_xincluded.xml +2 -0
  200. data/test/files/valid_bar.xml +2 -0
  201. data/test/files/xinclude.xml +4 -0
  202. data/test/helper.rb +124 -13
  203. data/test/html/sax/test_parser.rb +118 -4
  204. data/test/html/sax/test_parser_context.rb +46 -0
  205. data/test/html/sax/test_push_parser.rb +87 -0
  206. data/test/html/test_builder.rb +94 -8
  207. data/test/html/test_document.rb +626 -11
  208. data/test/html/test_document_encoding.rb +145 -0
  209. data/test/html/test_document_fragment.rb +301 -0
  210. data/test/html/test_element_description.rb +105 -0
  211. data/test/html/test_named_characters.rb +14 -0
  212. data/test/html/test_node.rb +212 -0
  213. data/test/html/test_node_encoding.rb +85 -0
  214. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +14 -0
  215. data/test/namespaces/test_namespaces_aliased_default.rb +24 -0
  216. data/test/namespaces/test_namespaces_in_builder_doc.rb +75 -0
  217. data/test/namespaces/test_namespaces_in_cloned_doc.rb +31 -0
  218. data/test/namespaces/test_namespaces_in_created_doc.rb +75 -0
  219. data/test/namespaces/test_namespaces_in_parsed_doc.rb +80 -0
  220. data/test/namespaces/test_namespaces_preservation.rb +31 -0
  221. data/test/test_convert_xpath.rb +2 -47
  222. data/test/test_css_cache.rb +45 -0
  223. data/test/test_encoding_handler.rb +48 -0
  224. data/test/test_memory_leak.rb +156 -0
  225. data/test/test_nokogiri.rb +103 -1
  226. data/test/test_soap4r_sax.rb +52 -0
  227. data/test/test_xslt_transforms.rb +293 -8
  228. data/test/xml/node/test_save_options.rb +28 -0
  229. data/test/xml/node/test_subclass.rb +44 -0
  230. data/test/xml/sax/test_parser.rb +309 -8
  231. data/test/xml/sax/test_parser_context.rb +115 -0
  232. data/test/xml/sax/test_push_parser.rb +157 -0
  233. data/test/xml/test_attr.rb +67 -0
  234. data/test/xml/test_attribute_decl.rb +86 -0
  235. data/test/xml/test_builder.rb +327 -2
  236. data/test/xml/test_c14n.rb +180 -0
  237. data/test/xml/test_cdata.rb +32 -2
  238. data/test/xml/test_comment.rb +40 -0
  239. data/test/xml/test_document.rb +846 -35
  240. data/test/xml/test_document_encoding.rb +31 -0
  241. data/test/xml/test_document_fragment.rb +271 -0
  242. data/test/xml/test_dtd.rb +153 -9
  243. data/test/xml/test_dtd_encoding.rb +31 -0
  244. data/test/xml/test_element_content.rb +56 -0
  245. data/test/xml/test_element_decl.rb +73 -0
  246. data/test/xml/test_entity_decl.rb +122 -0
  247. data/test/xml/test_entity_reference.rb +251 -0
  248. data/test/xml/test_namespace.rb +96 -0
  249. data/test/xml/test_node.rb +1126 -105
  250. data/test/xml/test_node_attributes.rb +115 -0
  251. data/test/xml/test_node_encoding.rb +69 -0
  252. data/test/xml/test_node_inheritance.rb +32 -0
  253. data/test/xml/test_node_reparenting.rb +549 -0
  254. data/test/xml/test_node_set.rb +668 -9
  255. data/test/xml/test_parse_options.rb +64 -0
  256. data/test/xml/test_processing_instruction.rb +30 -0
  257. data/test/xml/test_reader.rb +589 -0
  258. data/test/xml/test_reader_encoding.rb +134 -0
  259. data/test/xml/test_relax_ng.rb +60 -0
  260. data/test/xml/test_schema.rb +142 -0
  261. data/test/xml/test_syntax_error.rb +30 -0
  262. data/test/xml/test_text.rb +49 -2
  263. data/test/xml/test_unparented_node.rb +440 -0
  264. data/test/xml/test_xinclude.rb +83 -0
  265. data/test/xml/test_xpath.rb +445 -0
  266. data/test/xslt/test_custom_functions.rb +133 -0
  267. data/test/xslt/test_exception_handling.rb +37 -0
  268. data/test_all +107 -0
  269. metadata +459 -115
  270. data/History.txt +0 -6
  271. data/README.ja.txt +0 -86
  272. data/README.txt +0 -87
  273. data/ext/nokogiri/html_sax_parser.c +0 -32
  274. data/ext/nokogiri/html_sax_parser.h +0 -11
  275. data/ext/nokogiri/native.c +0 -40
  276. data/ext/nokogiri/native.h +0 -51
  277. data/ext/nokogiri/xml_xpath.c +0 -46
  278. data/ext/nokogiri/xml_xpath.h +0 -11
  279. data/lib/nokogiri/css/generated_parser.rb +0 -653
  280. data/lib/nokogiri/css/generated_tokenizer.rb +0 -159
  281. data/lib/nokogiri/decorators/hpricot/node.rb +0 -58
  282. data/lib/nokogiri/decorators/hpricot/node_set.rb +0 -14
  283. data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +0 -17
  284. data/lib/nokogiri/decorators/hpricot.rb +0 -3
  285. data/lib/nokogiri/decorators.rb +0 -1
  286. data/lib/nokogiri/hpricot.rb +0 -47
  287. data/lib/nokogiri/xml/after_handler.rb +0 -18
  288. data/lib/nokogiri/xml/before_handler.rb +0 -32
  289. data/lib/nokogiri/xml/element.rb +0 -6
  290. data/lib/nokogiri/xml/entity_declaration.rb +0 -9
  291. data/nokogiri.gemspec +0 -34
  292. data/test/hpricot/files/basic.xhtml +0 -17
  293. data/test/hpricot/files/boingboing.html +0 -2266
  294. data/test/hpricot/files/cy0.html +0 -3653
  295. data/test/hpricot/files/immob.html +0 -400
  296. data/test/hpricot/files/pace_application.html +0 -1320
  297. data/test/hpricot/files/tenderlove.html +0 -16
  298. data/test/hpricot/files/uswebgen.html +0 -220
  299. data/test/hpricot/files/utf8.html +0 -1054
  300. data/test/hpricot/files/week9.html +0 -1723
  301. data/test/hpricot/files/why.xml +0 -19
  302. data/test/hpricot/load_files.rb +0 -7
  303. data/test/hpricot/test_alter.rb +0 -67
  304. data/test/hpricot/test_builder.rb +0 -27
  305. data/test/hpricot/test_parser.rb +0 -423
  306. data/test/hpricot/test_paths.rb +0 -15
  307. data/test/hpricot/test_preserved.rb +0 -78
  308. data/test/hpricot/test_xml.rb +0 -30
  309. data/test/test_reader.rb +0 -222
@@ -3,12 +3,56 @@
3
3
  #include <libxslt/xsltInternals.h>
4
4
  #include <libxslt/xsltutils.h>
5
5
  #include <libxslt/transform.h>
6
+ #include <libexslt/exslt.h>
6
7
 
7
- static void dealloc(xsltStylesheetPtr doc)
8
+ VALUE xslt;
9
+
10
+ int vasprintf (char **strp, const char *fmt, va_list ap);
11
+ void vasprintf_free (void *p);
12
+
13
+ static void mark(nokogiriXsltStylesheetTuple *wrapper)
14
+ {
15
+ rb_gc_mark(wrapper->func_instances);
16
+ }
17
+
18
+ static void dealloc(nokogiriXsltStylesheetTuple *wrapper)
8
19
  {
20
+ xsltStylesheetPtr doc = wrapper->ss;
21
+
9
22
  NOKOGIRI_DEBUG_START(doc);
10
- xsltFreeStylesheet(doc); // commented out for now.
23
+ xsltFreeStylesheet(doc); /* commented out for now. */
11
24
  NOKOGIRI_DEBUG_END(doc);
25
+
26
+ free(wrapper);
27
+ }
28
+
29
+ static void xslt_generic_error_handler(void * ctx, const char *msg, ...)
30
+ {
31
+ char * message;
32
+
33
+ va_list args;
34
+ va_start(args, msg);
35
+ vasprintf(&message, msg, args);
36
+ va_end(args);
37
+
38
+ rb_str_cat2((VALUE)ctx, message);
39
+
40
+ vasprintf_free(message);
41
+ }
42
+
43
+ VALUE Nokogiri_wrap_xslt_stylesheet(xsltStylesheetPtr ss)
44
+ {
45
+ VALUE self;
46
+ nokogiriXsltStylesheetTuple *wrapper;
47
+
48
+ self = Data_Make_Struct(cNokogiriXsltStylesheet, nokogiriXsltStylesheetTuple,
49
+ mark, dealloc, wrapper);
50
+
51
+ ss->_private = (void *)self;
52
+ wrapper->ss = ss;
53
+ wrapper->func_instances = rb_ary_new();
54
+
55
+ return self;
12
56
  }
13
57
 
14
58
  /*
@@ -19,11 +63,27 @@ static void dealloc(xsltStylesheetPtr doc)
19
63
  */
20
64
  static VALUE parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
21
65
  {
22
- xmlDocPtr xml ;
66
+ xmlDocPtr xml, xml_cpy;
67
+ VALUE errstr, exception;
23
68
  xsltStylesheetPtr ss ;
24
69
  Data_Get_Struct(xmldocobj, xmlDoc, xml);
25
- ss = xsltParseStylesheetDoc(xmlCopyDoc(xml, 1)); /* 1 => recursive */
26
- return Data_Wrap_Struct(klass, NULL, dealloc, ss);
70
+ exsltRegisterAll();
71
+
72
+ errstr = rb_str_new(0, 0);
73
+ xsltSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
74
+
75
+ xml_cpy = xmlCopyDoc(xml, 1); /* 1 => recursive */
76
+ ss = xsltParseStylesheetDoc(xml_cpy);
77
+
78
+ xsltSetGenericErrorFunc(NULL, NULL);
79
+
80
+ if (!ss) {
81
+ xmlFreeDoc(xml_cpy);
82
+ exception = rb_exc_new3(rb_eRuntimeError, errstr);
83
+ rb_exc_raise(exception);
84
+ }
85
+
86
+ return Nokogiri_wrap_xslt_stylesheet(ss);
27
87
  }
28
88
 
29
89
 
@@ -36,73 +96,175 @@ static VALUE parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
36
96
  static VALUE serialize(VALUE self, VALUE xmlobj)
37
97
  {
38
98
  xmlDocPtr xml ;
39
- xsltStylesheetPtr ss ;
99
+ nokogiriXsltStylesheetTuple *wrapper;
40
100
  xmlChar* doc_ptr ;
41
101
  int doc_len ;
42
102
  VALUE rval ;
43
103
 
44
104
  Data_Get_Struct(xmlobj, xmlDoc, xml);
45
- Data_Get_Struct(self, xsltStylesheet, ss);
46
- xsltSaveResultToString(&doc_ptr, &doc_len, xml, ss);
47
- rval = rb_str_new((char*)doc_ptr, doc_len);
48
- free(doc_ptr);
105
+ Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
106
+ xsltSaveResultToString(&doc_ptr, &doc_len, xml, wrapper->ss);
107
+ rval = NOKOGIRI_STR_NEW(doc_ptr, doc_len);
108
+ xmlFree(doc_ptr);
49
109
  return rval ;
50
110
  }
51
111
 
112
+ static void swallow_superfluous_xml_errors(void * userdata, xmlErrorPtr error, ...)
113
+ {
114
+ }
52
115
 
53
116
  /*
54
117
  * call-seq:
55
- * apply_to(document, params)
118
+ * transform(document, params = [])
56
119
  *
57
120
  * Apply an XSLT stylesheet to an XML::Document.
58
121
  * +params+ is an array of strings used as XSLT parameters.
122
+ * returns Nokogiri::XML::Document
123
+ *
124
+ * Example:
125
+ *
126
+ * doc = Nokogiri::XML(File.read(ARGV[0]))
127
+ * xslt = Nokogiri::XSLT(File.read(ARGV[1]))
128
+ * puts xslt.transform(doc, ['key', 'value'])
129
+ *
59
130
  */
60
- static VALUE apply_to(int argc, VALUE* argv, VALUE self)
131
+ static VALUE transform(int argc, VALUE* argv, VALUE self)
61
132
  {
62
- VALUE xmldoc, paramobj ;
133
+ VALUE xmldoc, paramobj, errstr, exception ;
63
134
  xmlDocPtr xml ;
64
135
  xmlDocPtr result ;
65
- xsltStylesheetPtr ss ;
136
+ nokogiriXsltStylesheetTuple *wrapper;
66
137
  const char** params ;
67
- int param_len, j ;
68
- VALUE resultobj ;
138
+ long param_len, j ;
139
+ int parse_error_occurred ;
69
140
 
70
141
  rb_scan_args(argc, argv, "11", &xmldoc, &paramobj);
71
- if (paramobj == Qnil) { paramobj = rb_ary_new2(0) ; }
142
+ if (NIL_P(paramobj)) { paramobj = rb_ary_new2(0L) ; }
143
+ if (!rb_obj_is_kind_of(xmldoc, cNokogiriXmlDocument))
144
+ rb_raise(rb_eArgError, "argument must be a Nokogiri::XML::Document");
145
+
146
+ /* handle hashes as arguments. */
147
+ if(T_HASH == TYPE(paramobj)) {
148
+ paramobj = rb_funcall(paramobj, rb_intern("to_a"), 0);
149
+ paramobj = rb_funcall(paramobj, rb_intern("flatten"), 0);
150
+ }
151
+
152
+ Check_Type(paramobj, T_ARRAY);
72
153
 
73
154
  Data_Get_Struct(xmldoc, xmlDoc, xml);
74
- Data_Get_Struct(self, xsltStylesheet, ss);
155
+ Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
75
156
 
76
157
  param_len = RARRAY_LEN(paramobj);
77
158
  params = calloc((size_t)param_len+1, sizeof(char*));
78
159
  for (j = 0 ; j < param_len ; j++) {
79
160
  VALUE entry = rb_ary_entry(paramobj, j);
80
- const char * ptr = StringValuePtr(entry);
161
+ const char * ptr = StringValueCStr(entry);
81
162
  params[j] = ptr;
82
163
  }
83
164
  params[param_len] = 0 ;
84
165
 
85
- result = xsltApplyStylesheet(ss, xml, params);
166
+ errstr = rb_str_new(0, 0);
167
+ xsltSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
168
+ xmlSetGenericErrorFunc(NULL, (xmlGenericErrorFunc)&swallow_superfluous_xml_errors);
169
+
170
+ result = xsltApplyStylesheet(wrapper->ss, xml, params);
86
171
  free(params);
87
- resultobj = Nokogiri_wrap_xml_document(0, result) ;
88
- return rb_funcall(self, rb_intern("serialize"), 1, resultobj);
172
+
173
+ xsltSetGenericErrorFunc(NULL, NULL);
174
+ xmlSetGenericErrorFunc(NULL, NULL);
175
+
176
+ parse_error_occurred = (Qfalse == rb_funcall(errstr, rb_intern("empty?"), 0));
177
+
178
+ if (parse_error_occurred) {
179
+ exception = rb_exc_new3(rb_eRuntimeError, errstr);
180
+ rb_exc_raise(exception);
181
+ }
182
+
183
+ return Nokogiri_wrap_xml_document((VALUE)0, result) ;
184
+ }
185
+
186
+ static void method_caller(xmlXPathParserContextPtr ctxt, int nargs)
187
+ {
188
+ VALUE handler;
189
+ const char *function_name;
190
+ xsltTransformContextPtr transform;
191
+ const xmlChar *functionURI;
192
+
193
+ transform = xsltXPathGetTransformContext(ctxt);
194
+ functionURI = ctxt->context->functionURI;
195
+ handler = (VALUE)xsltGetExtData(transform, functionURI);
196
+ function_name = (const char*)(ctxt->context->function);
197
+
198
+ Nokogiri_marshal_xpath_funcall_and_return_values(ctxt, nargs, handler, (const char*)function_name);
199
+ }
200
+
201
+ static void * initFunc(xsltTransformContextPtr ctxt, const xmlChar *uri)
202
+ {
203
+ VALUE modules = rb_iv_get(xslt, "@modules");
204
+ VALUE obj = rb_hash_aref(modules, rb_str_new2((const char *)uri));
205
+ VALUE args = { Qfalse };
206
+ VALUE methods = rb_funcall(obj, rb_intern("instance_methods"), 1, args);
207
+ VALUE inst;
208
+ nokogiriXsltStylesheetTuple *wrapper;
209
+ int i;
210
+
211
+ for(i = 0; i < RARRAY_LEN(methods); i++) {
212
+ VALUE method_name = rb_obj_as_string(rb_ary_entry(methods, i));
213
+ xsltRegisterExtFunction(ctxt,
214
+ (unsigned char *)StringValueCStr(method_name), uri, method_caller);
215
+ }
216
+
217
+ Data_Get_Struct(ctxt->style->_private, nokogiriXsltStylesheetTuple,
218
+ wrapper);
219
+ inst = rb_class_new_instance(0, NULL, obj);
220
+ rb_ary_push(wrapper->func_instances, inst);
221
+
222
+ return (void *)inst;
223
+ }
224
+
225
+ static void shutdownFunc(xsltTransformContextPtr ctxt,
226
+ const xmlChar *uri, void *data)
227
+ {
228
+ nokogiriXsltStylesheetTuple *wrapper;
229
+
230
+ Data_Get_Struct(ctxt->style->_private, nokogiriXsltStylesheetTuple,
231
+ wrapper);
232
+
233
+ rb_ary_clear(wrapper->func_instances);
234
+ }
235
+
236
+ /*
237
+ * call-seq:
238
+ * register(uri, custom_handler_class)
239
+ *
240
+ * Register a class that implements custom XSLT transformation functions.
241
+ */
242
+ static VALUE registr(VALUE self, VALUE uri, VALUE obj)
243
+ {
244
+ VALUE modules = rb_iv_get(self, "@modules");
245
+ if(NIL_P(modules)) rb_raise(rb_eRuntimeError, "wtf! @modules isn't set");
246
+
247
+ rb_hash_aset(modules, uri, obj);
248
+ xsltRegisterExtModule((unsigned char *)StringValueCStr(uri), initFunc, shutdownFunc);
249
+ return self;
89
250
  }
90
251
 
91
252
  VALUE cNokogiriXsltStylesheet ;
92
253
  void init_xslt_stylesheet()
93
254
  {
94
- /*
95
- * HACK. This is so that rdoc will work with this C file.
96
- */
97
- /*
98
- VALUE nokogiri = rb_define_module("Nokogiri");
99
- VALUE xslt = rb_define_module_under(nokogiri, "XSLT");
100
- VALUE klass = rb_define_class_under(xslt, "Stylesheet", rb_cObject);
101
- */
102
-
103
- VALUE klass = cNokogiriXsltStylesheet = rb_const_get(mNokogiriXslt, rb_intern("Stylesheet"));
104
-
255
+ VALUE nokogiri;
256
+ VALUE klass;
257
+
258
+ nokogiri = rb_define_module("Nokogiri");
259
+ xslt = rb_define_module_under(nokogiri, "XSLT");
260
+ klass = rb_define_class_under(xslt, "Stylesheet", rb_cObject);
261
+
262
+ rb_iv_set(xslt, "@modules", rb_hash_new());
263
+
264
+ cNokogiriXsltStylesheet = klass;
265
+
105
266
  rb_define_singleton_method(klass, "parse_stylesheet_doc", parse_stylesheet_doc, 1);
267
+ rb_define_singleton_method(xslt, "register", registr, 2);
106
268
  rb_define_method(klass, "serialize", serialize, 1);
107
- rb_define_method(klass, "apply_to", apply_to, -1);
269
+ rb_define_method(klass, "transform", transform, -1);
108
270
  }
@@ -1,9 +1,14 @@
1
1
  #ifndef NOKOGIRI_XSLT_STYLESHEET
2
2
  #define NOKOGIRI_XSLT_STYLESHEET
3
3
 
4
- #include <native.h>
4
+ #include <nokogiri.h>
5
5
 
6
6
  void init_xslt_stylesheet();
7
7
 
8
8
  extern VALUE cNokogiriXsltStylesheet ;
9
+
10
+ typedef struct _nokogiriXsltStylesheetTuple {
11
+ xsltStylesheetPtr ss;
12
+ VALUE func_instances;
13
+ } nokogiriXsltStylesheetTuple;
9
14
  #endif
@@ -1,78 +1,33 @@
1
1
  module Nokogiri
2
2
  module CSS
3
3
  class Node
4
- attr_accessor :type, :value
4
+ ALLOW_COMBINATOR_ON_SELF = [:DIRECT_ADJACENT_SELECTOR, :FOLLOWING_SELECTOR, :CHILD_SELECTOR]
5
+
6
+ # Get the type of this node
7
+ attr_accessor :type
8
+ # Get the value of this node
9
+ attr_accessor :value
10
+
11
+ # Create a new Node with +type+ and +value+
5
12
  def initialize type, value
6
13
  @type = type
7
14
  @value = value
8
15
  end
9
16
 
17
+ # Accept +visitor+
10
18
  def accept visitor
11
19
  visitor.send(:"visit_#{type.to_s.downcase}", self)
12
20
  end
13
21
 
14
- def to_xpath prefix = '//', preprocess = true
15
- self.preprocess! if preprocess
16
- prefix + XPathVisitor.new.accept(self)
17
- end
18
-
19
- def preprocess!
20
- ### Deal with nth-child
21
- matches = find_by_type(
22
- [:CONDITIONAL_SELECTOR,
23
- [:ELEMENT_NAME],
24
- [:PSEUDO_CLASS,
25
- [:FUNCTION]
26
- ]
27
- ]
28
- )
29
- matches.each do |match|
30
- if match.value[1].value[0].value[0] =~ /^nth-child/
31
- tag_name = match.value[0].value.first
32
- match.value[0].value = ['*']
33
- match.value[1] = Node.new(:COMBINATOR, [
34
- match.value[1].value[0],
35
- Node.new(:FUNCTION, ['self(', tag_name])
36
- ])
37
- end
38
- if match.value[1].value[0].value[0] =~ /^nth-last-child/
39
- tag_name = match.value[0].value.first
40
- match.value[0].value = ['*']
41
- match.value[1] = Node.new(:COMBINATOR, [
42
- match.value[1].value[0],
43
- Node.new(:FUNCTION, ['self(', tag_name])
44
- ])
45
- end
46
- end
47
-
48
- ### Deal with first-child, last-child
49
- matches = find_by_type(
50
- [:CONDITIONAL_SELECTOR,
51
- [:ELEMENT_NAME], [:PSEUDO_CLASS]
52
- ])
53
- matches.each do |match|
54
- if ['first-child', 'last-child'].include?(match.value[1].value.first)
55
- which = match.value[1].value.first.gsub(/-\w*$/, '')
56
- tag_name = match.value[0].value.first
57
- match.value[0].value = ['*']
58
- match.value[1] = Node.new(:COMBINATOR, [
59
- Node.new(:FUNCTION, ["#{which}("]),
60
- Node.new(:FUNCTION, ['self(', tag_name])
61
- ])
62
- elsif 'only-child' == match.value[1].value.first
63
- tag_name = match.value[0].value.first
64
- match.value[0].value = ['*']
65
- match.value[1] = Node.new(:COMBINATOR, [
66
- Node.new(:FUNCTION, ["#{match.value[1].value.first}("]),
67
- Node.new(:FUNCTION, ['self(', tag_name])
68
- ])
69
- end
70
- end
71
-
72
- self
22
+ ###
23
+ # Convert this CSS node to xpath with +prefix+ using +visitor+
24
+ def to_xpath prefix = '//', visitor = XPathVisitor.new
25
+ prefix = '.' if ALLOW_COMBINATOR_ON_SELF.include?(type) && value.first.nil?
26
+ prefix + visitor.accept(self)
73
27
  end
74
28
 
75
- def find_by_type(types)
29
+ # Find a node by type using +types+
30
+ def find_by_type types
76
31
  matches = []
77
32
  matches << self if to_type == types
78
33
  @value.each do |v|
@@ -81,12 +36,14 @@ module Nokogiri
81
36
  matches
82
37
  end
83
38
 
39
+ # Convert to_type
84
40
  def to_type
85
41
  [@type] + @value.map { |n|
86
42
  n.to_type if n.respond_to?(:to_type)
87
43
  }.compact
88
44
  end
89
45
 
46
+ # Convert to array
90
47
  def to_a
91
48
  [@type] + @value.map { |n| n.respond_to?(:to_a) ? n.to_a : [n] }
92
49
  end