nokogiri 1.13.0-x64-mingw-ucrt

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 (195) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +5 -0
  3. data/LICENSE-DEPENDENCIES.md +1903 -0
  4. data/LICENSE.md +9 -0
  5. data/README.md +280 -0
  6. data/bin/nokogiri +131 -0
  7. data/dependencies.yml +73 -0
  8. data/ext/nokogiri/depend +38 -0
  9. data/ext/nokogiri/extconf.rb +1000 -0
  10. data/ext/nokogiri/gumbo.c +584 -0
  11. data/ext/nokogiri/html4_document.c +166 -0
  12. data/ext/nokogiri/html4_element_description.c +294 -0
  13. data/ext/nokogiri/html4_entity_lookup.c +37 -0
  14. data/ext/nokogiri/html4_sax_parser_context.c +120 -0
  15. data/ext/nokogiri/html4_sax_push_parser.c +95 -0
  16. data/ext/nokogiri/include/libexslt/exslt.h +102 -0
  17. data/ext/nokogiri/include/libexslt/exsltconfig.h +70 -0
  18. data/ext/nokogiri/include/libexslt/exsltexports.h +140 -0
  19. data/ext/nokogiri/include/libxml2/libxml/DOCBparser.h +96 -0
  20. data/ext/nokogiri/include/libxml2/libxml/HTMLparser.h +306 -0
  21. data/ext/nokogiri/include/libxml2/libxml/HTMLtree.h +147 -0
  22. data/ext/nokogiri/include/libxml2/libxml/SAX.h +173 -0
  23. data/ext/nokogiri/include/libxml2/libxml/SAX2.h +178 -0
  24. data/ext/nokogiri/include/libxml2/libxml/c14n.h +128 -0
  25. data/ext/nokogiri/include/libxml2/libxml/catalog.h +182 -0
  26. data/ext/nokogiri/include/libxml2/libxml/chvalid.h +230 -0
  27. data/ext/nokogiri/include/libxml2/libxml/debugXML.h +217 -0
  28. data/ext/nokogiri/include/libxml2/libxml/dict.h +79 -0
  29. data/ext/nokogiri/include/libxml2/libxml/encoding.h +245 -0
  30. data/ext/nokogiri/include/libxml2/libxml/entities.h +151 -0
  31. data/ext/nokogiri/include/libxml2/libxml/globals.h +508 -0
  32. data/ext/nokogiri/include/libxml2/libxml/hash.h +236 -0
  33. data/ext/nokogiri/include/libxml2/libxml/list.h +137 -0
  34. data/ext/nokogiri/include/libxml2/libxml/nanoftp.h +163 -0
  35. data/ext/nokogiri/include/libxml2/libxml/nanohttp.h +81 -0
  36. data/ext/nokogiri/include/libxml2/libxml/parser.h +1243 -0
  37. data/ext/nokogiri/include/libxml2/libxml/parserInternals.h +644 -0
  38. data/ext/nokogiri/include/libxml2/libxml/pattern.h +100 -0
  39. data/ext/nokogiri/include/libxml2/libxml/relaxng.h +217 -0
  40. data/ext/nokogiri/include/libxml2/libxml/schemasInternals.h +958 -0
  41. data/ext/nokogiri/include/libxml2/libxml/schematron.h +142 -0
  42. data/ext/nokogiri/include/libxml2/libxml/threads.h +89 -0
  43. data/ext/nokogiri/include/libxml2/libxml/tree.h +1311 -0
  44. data/ext/nokogiri/include/libxml2/libxml/uri.h +94 -0
  45. data/ext/nokogiri/include/libxml2/libxml/valid.h +458 -0
  46. data/ext/nokogiri/include/libxml2/libxml/xinclude.h +129 -0
  47. data/ext/nokogiri/include/libxml2/libxml/xlink.h +189 -0
  48. data/ext/nokogiri/include/libxml2/libxml/xmlIO.h +368 -0
  49. data/ext/nokogiri/include/libxml2/libxml/xmlautomata.h +146 -0
  50. data/ext/nokogiri/include/libxml2/libxml/xmlerror.h +946 -0
  51. data/ext/nokogiri/include/libxml2/libxml/xmlexports.h +77 -0
  52. data/ext/nokogiri/include/libxml2/libxml/xmlmemory.h +224 -0
  53. data/ext/nokogiri/include/libxml2/libxml/xmlmodule.h +57 -0
  54. data/ext/nokogiri/include/libxml2/libxml/xmlreader.h +428 -0
  55. data/ext/nokogiri/include/libxml2/libxml/xmlregexp.h +222 -0
  56. data/ext/nokogiri/include/libxml2/libxml/xmlsave.h +88 -0
  57. data/ext/nokogiri/include/libxml2/libxml/xmlschemas.h +246 -0
  58. data/ext/nokogiri/include/libxml2/libxml/xmlschemastypes.h +151 -0
  59. data/ext/nokogiri/include/libxml2/libxml/xmlstring.h +140 -0
  60. data/ext/nokogiri/include/libxml2/libxml/xmlunicode.h +202 -0
  61. data/ext/nokogiri/include/libxml2/libxml/xmlversion.h +485 -0
  62. data/ext/nokogiri/include/libxml2/libxml/xmlwriter.h +488 -0
  63. data/ext/nokogiri/include/libxml2/libxml/xpath.h +564 -0
  64. data/ext/nokogiri/include/libxml2/libxml/xpathInternals.h +632 -0
  65. data/ext/nokogiri/include/libxml2/libxml/xpointer.h +114 -0
  66. data/ext/nokogiri/include/libxslt/attributes.h +38 -0
  67. data/ext/nokogiri/include/libxslt/documents.h +93 -0
  68. data/ext/nokogiri/include/libxslt/extensions.h +262 -0
  69. data/ext/nokogiri/include/libxslt/extra.h +72 -0
  70. data/ext/nokogiri/include/libxslt/functions.h +78 -0
  71. data/ext/nokogiri/include/libxslt/imports.h +75 -0
  72. data/ext/nokogiri/include/libxslt/keys.h +53 -0
  73. data/ext/nokogiri/include/libxslt/namespaces.h +68 -0
  74. data/ext/nokogiri/include/libxslt/numbersInternals.h +73 -0
  75. data/ext/nokogiri/include/libxslt/pattern.h +84 -0
  76. data/ext/nokogiri/include/libxslt/preproc.h +43 -0
  77. data/ext/nokogiri/include/libxslt/security.h +104 -0
  78. data/ext/nokogiri/include/libxslt/templates.h +77 -0
  79. data/ext/nokogiri/include/libxslt/transform.h +207 -0
  80. data/ext/nokogiri/include/libxslt/variables.h +118 -0
  81. data/ext/nokogiri/include/libxslt/xslt.h +110 -0
  82. data/ext/nokogiri/include/libxslt/xsltInternals.h +1978 -0
  83. data/ext/nokogiri/include/libxslt/xsltconfig.h +180 -0
  84. data/ext/nokogiri/include/libxslt/xsltexports.h +142 -0
  85. data/ext/nokogiri/include/libxslt/xsltlocale.h +76 -0
  86. data/ext/nokogiri/include/libxslt/xsltutils.h +313 -0
  87. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  88. data/ext/nokogiri/nokogiri.c +278 -0
  89. data/ext/nokogiri/nokogiri.h +223 -0
  90. data/ext/nokogiri/test_global_handlers.c +40 -0
  91. data/ext/nokogiri/xml_attr.c +103 -0
  92. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  93. data/ext/nokogiri/xml_cdata.c +57 -0
  94. data/ext/nokogiri/xml_comment.c +62 -0
  95. data/ext/nokogiri/xml_document.c +680 -0
  96. data/ext/nokogiri/xml_document_fragment.c +44 -0
  97. data/ext/nokogiri/xml_dtd.c +208 -0
  98. data/ext/nokogiri/xml_element_content.c +128 -0
  99. data/ext/nokogiri/xml_element_decl.c +69 -0
  100. data/ext/nokogiri/xml_encoding_handler.c +104 -0
  101. data/ext/nokogiri/xml_entity_decl.c +112 -0
  102. data/ext/nokogiri/xml_entity_reference.c +50 -0
  103. data/ext/nokogiri/xml_namespace.c +120 -0
  104. data/ext/nokogiri/xml_node.c +2144 -0
  105. data/ext/nokogiri/xml_node_set.c +498 -0
  106. data/ext/nokogiri/xml_processing_instruction.c +54 -0
  107. data/ext/nokogiri/xml_reader.c +719 -0
  108. data/ext/nokogiri/xml_relax_ng.c +185 -0
  109. data/ext/nokogiri/xml_sax_parser.c +310 -0
  110. data/ext/nokogiri/xml_sax_parser_context.c +281 -0
  111. data/ext/nokogiri/xml_sax_push_parser.c +168 -0
  112. data/ext/nokogiri/xml_schema.c +284 -0
  113. data/ext/nokogiri/xml_syntax_error.c +85 -0
  114. data/ext/nokogiri/xml_text.c +48 -0
  115. data/ext/nokogiri/xml_xpath_context.c +406 -0
  116. data/ext/nokogiri/xslt_stylesheet.c +264 -0
  117. data/gumbo-parser/CHANGES.md +63 -0
  118. data/gumbo-parser/Makefile +101 -0
  119. data/gumbo-parser/THANKS +27 -0
  120. data/lib/nokogiri/3.1/nokogiri.so +0 -0
  121. data/lib/nokogiri/class_resolver.rb +67 -0
  122. data/lib/nokogiri/css/node.rb +54 -0
  123. data/lib/nokogiri/css/parser.rb +759 -0
  124. data/lib/nokogiri/css/parser.y +280 -0
  125. data/lib/nokogiri/css/parser_extras.rb +94 -0
  126. data/lib/nokogiri/css/syntax_error.rb +9 -0
  127. data/lib/nokogiri/css/tokenizer.rb +155 -0
  128. data/lib/nokogiri/css/tokenizer.rex +56 -0
  129. data/lib/nokogiri/css/xpath_visitor.rb +359 -0
  130. data/lib/nokogiri/css.rb +60 -0
  131. data/lib/nokogiri/decorators/slop.rb +44 -0
  132. data/lib/nokogiri/extension.rb +31 -0
  133. data/lib/nokogiri/gumbo.rb +15 -0
  134. data/lib/nokogiri/html.rb +48 -0
  135. data/lib/nokogiri/html4/builder.rb +37 -0
  136. data/lib/nokogiri/html4/document.rb +331 -0
  137. data/lib/nokogiri/html4/document_fragment.rb +54 -0
  138. data/lib/nokogiri/html4/element_description.rb +25 -0
  139. data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
  140. data/lib/nokogiri/html4/entity_lookup.rb +15 -0
  141. data/lib/nokogiri/html4/sax/parser.rb +61 -0
  142. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  143. data/lib/nokogiri/html4/sax/push_parser.rb +37 -0
  144. data/lib/nokogiri/html4.rb +46 -0
  145. data/lib/nokogiri/html5/document.rb +88 -0
  146. data/lib/nokogiri/html5/document_fragment.rb +83 -0
  147. data/lib/nokogiri/html5/node.rb +96 -0
  148. data/lib/nokogiri/html5.rb +477 -0
  149. data/lib/nokogiri/jruby/dependencies.rb +21 -0
  150. data/lib/nokogiri/syntax_error.rb +6 -0
  151. data/lib/nokogiri/version/constant.rb +6 -0
  152. data/lib/nokogiri/version/info.rb +221 -0
  153. data/lib/nokogiri/version.rb +4 -0
  154. data/lib/nokogiri/xml/attr.rb +17 -0
  155. data/lib/nokogiri/xml/attribute_decl.rb +20 -0
  156. data/lib/nokogiri/xml/builder.rb +485 -0
  157. data/lib/nokogiri/xml/cdata.rb +13 -0
  158. data/lib/nokogiri/xml/character_data.rb +9 -0
  159. data/lib/nokogiri/xml/document.rb +418 -0
  160. data/lib/nokogiri/xml/document_fragment.rb +162 -0
  161. data/lib/nokogiri/xml/dtd.rb +34 -0
  162. data/lib/nokogiri/xml/element_content.rb +38 -0
  163. data/lib/nokogiri/xml/element_decl.rb +15 -0
  164. data/lib/nokogiri/xml/entity_decl.rb +21 -0
  165. data/lib/nokogiri/xml/entity_reference.rb +20 -0
  166. data/lib/nokogiri/xml/namespace.rb +16 -0
  167. data/lib/nokogiri/xml/node/save_options.rb +65 -0
  168. data/lib/nokogiri/xml/node.rb +1402 -0
  169. data/lib/nokogiri/xml/node_set.rb +364 -0
  170. data/lib/nokogiri/xml/notation.rb +19 -0
  171. data/lib/nokogiri/xml/parse_options.rb +133 -0
  172. data/lib/nokogiri/xml/pp/character_data.rb +21 -0
  173. data/lib/nokogiri/xml/pp/node.rb +55 -0
  174. data/lib/nokogiri/xml/pp.rb +4 -0
  175. data/lib/nokogiri/xml/processing_instruction.rb +10 -0
  176. data/lib/nokogiri/xml/reader.rb +107 -0
  177. data/lib/nokogiri/xml/relax_ng.rb +38 -0
  178. data/lib/nokogiri/xml/sax/document.rb +167 -0
  179. data/lib/nokogiri/xml/sax/parser.rb +125 -0
  180. data/lib/nokogiri/xml/sax/parser_context.rb +21 -0
  181. data/lib/nokogiri/xml/sax/push_parser.rb +61 -0
  182. data/lib/nokogiri/xml/sax.rb +6 -0
  183. data/lib/nokogiri/xml/schema.rb +73 -0
  184. data/lib/nokogiri/xml/searchable.rb +259 -0
  185. data/lib/nokogiri/xml/syntax_error.rb +71 -0
  186. data/lib/nokogiri/xml/text.rb +11 -0
  187. data/lib/nokogiri/xml/xpath/syntax_error.rb +13 -0
  188. data/lib/nokogiri/xml/xpath.rb +21 -0
  189. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  190. data/lib/nokogiri/xml.rb +75 -0
  191. data/lib/nokogiri/xslt/stylesheet.rb +27 -0
  192. data/lib/nokogiri/xslt.rb +58 -0
  193. data/lib/nokogiri.rb +128 -0
  194. data/lib/xsd/xmlparser/nokogiri.rb +104 -0
  195. metadata +536 -0
@@ -0,0 +1,85 @@
1
+ #include <nokogiri.h>
2
+
3
+ VALUE cNokogiriXmlSyntaxError;
4
+
5
+ void
6
+ Nokogiri_structured_error_func_save(libxmlStructuredErrorHandlerState *handler_state)
7
+ {
8
+ /* this method is tightly coupled to the implementation of xmlSetStructuredErrorFunc */
9
+ handler_state->user_data = xmlStructuredErrorContext;
10
+ handler_state->handler = xmlStructuredError;
11
+ }
12
+
13
+ void
14
+ Nokogiri_structured_error_func_save_and_set(libxmlStructuredErrorHandlerState *handler_state,
15
+ void *user_data,
16
+ xmlStructuredErrorFunc handler)
17
+ {
18
+ Nokogiri_structured_error_func_save(handler_state);
19
+ xmlSetStructuredErrorFunc(user_data, handler);
20
+ }
21
+
22
+ void
23
+ Nokogiri_structured_error_func_restore(libxmlStructuredErrorHandlerState *handler_state)
24
+ {
25
+ xmlSetStructuredErrorFunc(handler_state->user_data, handler_state->handler);
26
+ }
27
+
28
+ void
29
+ Nokogiri_error_array_pusher(void *ctx, xmlErrorPtr error)
30
+ {
31
+ VALUE list = (VALUE)ctx;
32
+ Check_Type(list, T_ARRAY);
33
+ rb_ary_push(list, Nokogiri_wrap_xml_syntax_error(error));
34
+ }
35
+
36
+ void
37
+ Nokogiri_error_raise(void *ctx, xmlErrorPtr error)
38
+ {
39
+ rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
40
+ }
41
+
42
+ VALUE
43
+ Nokogiri_wrap_xml_syntax_error(xmlErrorPtr error)
44
+ {
45
+ VALUE msg, e, klass;
46
+
47
+ klass = cNokogiriXmlSyntaxError;
48
+
49
+ if (error && error->domain == XML_FROM_XPATH) {
50
+ klass = cNokogiriXmlXpathSyntaxError;
51
+ }
52
+
53
+ msg = (error && error->message) ? NOKOGIRI_STR_NEW2(error->message) : Qnil;
54
+
55
+ e = rb_class_new_instance(
56
+ 1,
57
+ &msg,
58
+ klass
59
+ );
60
+
61
+ if (error) {
62
+ rb_iv_set(e, "@domain", INT2NUM(error->domain));
63
+ rb_iv_set(e, "@code", INT2NUM(error->code));
64
+ rb_iv_set(e, "@level", INT2NUM((short)error->level));
65
+ rb_iv_set(e, "@file", RBSTR_OR_QNIL(error->file));
66
+ rb_iv_set(e, "@line", INT2NUM(error->line));
67
+ rb_iv_set(e, "@str1", RBSTR_OR_QNIL(error->str1));
68
+ rb_iv_set(e, "@str2", RBSTR_OR_QNIL(error->str2));
69
+ rb_iv_set(e, "@str3", RBSTR_OR_QNIL(error->str3));
70
+ rb_iv_set(e, "@int1", INT2NUM(error->int1));
71
+ rb_iv_set(e, "@column", INT2NUM(error->int2));
72
+ }
73
+
74
+ return e;
75
+ }
76
+
77
+ void
78
+ noko_init_xml_syntax_error()
79
+ {
80
+ assert(cNokogiriSyntaxError);
81
+ /*
82
+ * The XML::SyntaxError is raised on parse errors
83
+ */
84
+ cNokogiriXmlSyntaxError = rb_define_class_under(mNokogiriXml, "SyntaxError", cNokogiriSyntaxError);
85
+ }
@@ -0,0 +1,48 @@
1
+ #include <nokogiri.h>
2
+
3
+ VALUE cNokogiriXmlText ;
4
+
5
+ /*
6
+ * call-seq:
7
+ * new(content, document)
8
+ *
9
+ * Create a new Text element on the +document+ with +content+
10
+ */
11
+ static VALUE
12
+ new (int argc, VALUE *argv, VALUE klass)
13
+ {
14
+ xmlDocPtr doc;
15
+ xmlNodePtr node;
16
+ VALUE string;
17
+ VALUE document;
18
+ VALUE rest;
19
+ VALUE rb_node;
20
+
21
+ rb_scan_args(argc, argv, "2*", &string, &document, &rest);
22
+
23
+ Data_Get_Struct(document, xmlDoc, doc);
24
+
25
+ node = xmlNewText((xmlChar *)StringValueCStr(string));
26
+ node->doc = doc->doc;
27
+
28
+ noko_xml_document_pin_node(node);
29
+
30
+ rb_node = noko_xml_node_wrap(klass, node) ;
31
+ rb_obj_call_init(rb_node, argc, argv);
32
+
33
+ if (rb_block_given_p()) { rb_yield(rb_node); }
34
+
35
+ return rb_node;
36
+ }
37
+
38
+ void
39
+ noko_init_xml_text()
40
+ {
41
+ assert(cNokogiriXmlCharacterData);
42
+ /*
43
+ * Wraps Text nodes.
44
+ */
45
+ cNokogiriXmlText = rb_define_class_under(mNokogiriXml, "Text", cNokogiriXmlCharacterData);
46
+
47
+ rb_define_singleton_method(cNokogiriXmlText, "new", new, -1);
48
+ }
@@ -0,0 +1,406 @@
1
+ #include <nokogiri.h>
2
+
3
+ VALUE cNokogiriXmlXpathContext;
4
+
5
+ /*
6
+ * these constants have matching declarations in
7
+ * ext/java/nokogiri/internals/NokogiriNamespaceContext.java
8
+ */
9
+ static const xmlChar *NOKOGIRI_BUILTIN_PREFIX = (const xmlChar *)"nokogiri-builtin";
10
+ static const xmlChar *NOKOGIRI_BUILTIN_URI = (const xmlChar *)"https://www.nokogiri.org/default_ns/ruby/builtins";
11
+
12
+ static void
13
+ deallocate(xmlXPathContextPtr ctx)
14
+ {
15
+ NOKOGIRI_DEBUG_START(ctx);
16
+ xmlXPathFreeContext(ctx);
17
+ NOKOGIRI_DEBUG_END(ctx);
18
+ }
19
+
20
+ /* find a CSS class in an HTML element's `class` attribute */
21
+ static const xmlChar *
22
+ builtin_css_class(const xmlChar *str, const xmlChar *val)
23
+ {
24
+ int val_len;
25
+
26
+ if (str == NULL) { return (NULL); }
27
+ if (val == NULL) { return (NULL); }
28
+
29
+ val_len = xmlStrlen(val);
30
+ if (val_len == 0) { return (str); }
31
+
32
+ while (*str != 0) {
33
+ if ((*str == *val) && !xmlStrncmp(str, val, val_len)) {
34
+ const xmlChar *next_byte = str + val_len;
35
+
36
+ /* only match if the next byte is whitespace or end of string */
37
+ if ((*next_byte == 0) || (IS_BLANK_CH(*next_byte))) {
38
+ return ((const xmlChar *)str);
39
+ }
40
+ }
41
+
42
+ /* advance str to whitespace */
43
+ while ((*str != 0) && !IS_BLANK_CH(*str)) {
44
+ str++;
45
+ }
46
+
47
+ /* advance str to start of next word or end of string */
48
+ while ((*str != 0) && IS_BLANK_CH(*str)) {
49
+ str++;
50
+ }
51
+ }
52
+
53
+ return (NULL);
54
+ }
55
+
56
+ /* xmlXPathFunction to wrap builtin_css_class() */
57
+ static void
58
+ xpath_builtin_css_class(xmlXPathParserContextPtr ctxt, int nargs)
59
+ {
60
+ xmlXPathObjectPtr hay, needle;
61
+
62
+ CHECK_ARITY(2);
63
+
64
+ CAST_TO_STRING;
65
+ needle = valuePop(ctxt);
66
+ if ((needle == NULL) || (needle->type != XPATH_STRING)) {
67
+ xmlXPathFreeObject(needle);
68
+ XP_ERROR(XPATH_INVALID_TYPE);
69
+ }
70
+
71
+ CAST_TO_STRING;
72
+ hay = valuePop(ctxt);
73
+ if ((hay == NULL) || (hay->type != XPATH_STRING)) {
74
+ xmlXPathFreeObject(hay);
75
+ xmlXPathFreeObject(needle);
76
+ XP_ERROR(XPATH_INVALID_TYPE);
77
+ }
78
+
79
+ if (builtin_css_class(hay->stringval, needle->stringval)) {
80
+ valuePush(ctxt, xmlXPathNewBoolean(1));
81
+ } else {
82
+ valuePush(ctxt, xmlXPathNewBoolean(0));
83
+ }
84
+
85
+ xmlXPathFreeObject(hay);
86
+ xmlXPathFreeObject(needle);
87
+ }
88
+
89
+
90
+ /* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should ignore namespaces */
91
+ static void
92
+ xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
93
+ {
94
+ xmlXPathObjectPtr element_name;
95
+
96
+ assert(ctxt->context->node);
97
+
98
+ CHECK_ARITY(1);
99
+ CAST_TO_STRING;
100
+ CHECK_TYPE(XPATH_STRING);
101
+ element_name = valuePop(ctxt);
102
+
103
+ valuePush(ctxt, xmlXPathNewBoolean(xmlStrEqual(ctxt->context->node->name, element_name->stringval)));
104
+
105
+ xmlXPathFreeObject(element_name);
106
+ }
107
+
108
+
109
+ /*
110
+ * call-seq:
111
+ * register_ns(prefix, uri)
112
+ *
113
+ * Register the namespace with +prefix+ and +uri+.
114
+ */
115
+ static VALUE
116
+ register_ns(VALUE self, VALUE prefix, VALUE uri)
117
+ {
118
+ xmlXPathContextPtr ctx;
119
+ Data_Get_Struct(self, xmlXPathContext, ctx);
120
+
121
+ xmlXPathRegisterNs(ctx,
122
+ (const xmlChar *)StringValueCStr(prefix),
123
+ (const xmlChar *)StringValueCStr(uri)
124
+ );
125
+ return self;
126
+ }
127
+
128
+ /*
129
+ * call-seq:
130
+ * register_variable(name, value)
131
+ *
132
+ * Register the variable +name+ with +value+.
133
+ */
134
+ static VALUE
135
+ register_variable(VALUE self, VALUE name, VALUE value)
136
+ {
137
+ xmlXPathContextPtr ctx;
138
+ xmlXPathObjectPtr xmlValue;
139
+ Data_Get_Struct(self, xmlXPathContext, ctx);
140
+
141
+ xmlValue = xmlXPathNewCString(StringValueCStr(value));
142
+
143
+ xmlXPathRegisterVariable(ctx,
144
+ (const xmlChar *)StringValueCStr(name),
145
+ xmlValue
146
+ );
147
+
148
+ return self;
149
+ }
150
+
151
+
152
+ /*
153
+ * convert an XPath object into a Ruby object of the appropriate type.
154
+ * returns Qundef if no conversion was possible.
155
+ */
156
+ static VALUE
157
+ xpath2ruby(xmlXPathObjectPtr xobj, xmlXPathContextPtr xctx)
158
+ {
159
+ VALUE retval;
160
+
161
+ assert(xctx->doc);
162
+ assert(DOC_RUBY_OBJECT_TEST(xctx->doc));
163
+
164
+ switch (xobj->type) {
165
+ case XPATH_STRING:
166
+ retval = NOKOGIRI_STR_NEW2(xobj->stringval);
167
+ xmlFree(xobj->stringval);
168
+ return retval;
169
+
170
+ case XPATH_NODESET:
171
+ return noko_xml_node_set_wrap(xobj->nodesetval,
172
+ DOC_RUBY_OBJECT(xctx->doc));
173
+
174
+ case XPATH_NUMBER:
175
+ return rb_float_new(xobj->floatval);
176
+
177
+ case XPATH_BOOLEAN:
178
+ return (xobj->boolval == 1) ? Qtrue : Qfalse;
179
+
180
+ default:
181
+ return Qundef;
182
+ }
183
+ }
184
+
185
+ void
186
+ Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, int nargs, VALUE handler,
187
+ const char *function_name)
188
+ {
189
+ VALUE result, doc;
190
+ VALUE *argv;
191
+ VALUE node_set = Qnil;
192
+ xmlNodeSetPtr xml_node_set = NULL;
193
+ xmlXPathObjectPtr obj;
194
+
195
+ assert(ctx->context->doc);
196
+ assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc));
197
+
198
+ argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE));
199
+ for (int j = 0 ; j < nargs ; ++j) {
200
+ rb_gc_register_address(&argv[j]);
201
+ }
202
+
203
+ doc = DOC_RUBY_OBJECT(ctx->context->doc);
204
+
205
+ for (int j = nargs - 1 ; j >= 0 ; --j) {
206
+ obj = valuePop(ctx);
207
+ argv[j] = xpath2ruby(obj, ctx->context);
208
+ if (argv[j] == Qundef) {
209
+ argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj));
210
+ }
211
+ xmlXPathFreeNodeSetList(obj);
212
+ }
213
+
214
+ result = rb_funcall2(handler, rb_intern((const char *)function_name), nargs, argv);
215
+
216
+ for (int j = 0 ; j < nargs ; ++j) {
217
+ rb_gc_unregister_address(&argv[j]);
218
+ }
219
+ free(argv);
220
+
221
+ switch (TYPE(result)) {
222
+ case T_FLOAT:
223
+ case T_BIGNUM:
224
+ case T_FIXNUM:
225
+ xmlXPathReturnNumber(ctx, NUM2DBL(result));
226
+ break;
227
+ case T_STRING:
228
+ xmlXPathReturnString(
229
+ ctx,
230
+ xmlCharStrdup(StringValueCStr(result))
231
+ );
232
+ break;
233
+ case T_TRUE:
234
+ xmlXPathReturnTrue(ctx);
235
+ break;
236
+ case T_FALSE:
237
+ xmlXPathReturnFalse(ctx);
238
+ break;
239
+ case T_NIL:
240
+ break;
241
+ case T_ARRAY: {
242
+ VALUE args[2];
243
+ args[0] = doc;
244
+ args[1] = result;
245
+ node_set = rb_class_new_instance(2, args, cNokogiriXmlNodeSet);
246
+ Data_Get_Struct(node_set, xmlNodeSet, xml_node_set);
247
+ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
248
+ }
249
+ break;
250
+ case T_DATA:
251
+ if (rb_obj_is_kind_of(result, cNokogiriXmlNodeSet)) {
252
+ Data_Get_Struct(result, xmlNodeSet, xml_node_set);
253
+ /* Copy the node set, otherwise it will get GC'd. */
254
+ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
255
+ break;
256
+ }
257
+ default:
258
+ rb_raise(rb_eRuntimeError, "Invalid return type");
259
+ }
260
+ }
261
+
262
+ static void
263
+ ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
264
+ {
265
+ VALUE handler = Qnil;
266
+ const char *function = NULL ;
267
+
268
+ assert(ctx);
269
+ assert(ctx->context);
270
+ assert(ctx->context->userData);
271
+ assert(ctx->context->function);
272
+
273
+ handler = (VALUE)(ctx->context->userData);
274
+ function = (const char *)(ctx->context->function);
275
+
276
+ Nokogiri_marshal_xpath_funcall_and_return_values(ctx, nargs, handler, function);
277
+ }
278
+
279
+ static xmlXPathFunction
280
+ lookup(void *ctx,
281
+ const xmlChar *name,
282
+ const xmlChar *ns_uri)
283
+ {
284
+ VALUE xpath_handler = (VALUE)ctx;
285
+ if (rb_respond_to(xpath_handler, rb_intern((const char *)name))) {
286
+ return ruby_funcall;
287
+ }
288
+
289
+ return NULL;
290
+ }
291
+
292
+ NORETURN(static void xpath_generic_exception_handler(void *ctx, const char *msg, ...));
293
+ static void
294
+ xpath_generic_exception_handler(void *ctx, const char *msg, ...)
295
+ {
296
+ char *message;
297
+
298
+ va_list args;
299
+ va_start(args, msg);
300
+ vasprintf(&message, msg, args);
301
+ va_end(args);
302
+
303
+ rb_raise(rb_eRuntimeError, "%s", message);
304
+ }
305
+
306
+ /*
307
+ * call-seq:
308
+ * evaluate(search_path, handler = nil)
309
+ *
310
+ * Evaluate the +search_path+ returning an XML::XPath object.
311
+ */
312
+ static VALUE
313
+ evaluate(int argc, VALUE *argv, VALUE self)
314
+ {
315
+ VALUE search_path, xpath_handler;
316
+ VALUE retval = Qnil;
317
+ xmlXPathContextPtr ctx;
318
+ xmlXPathObjectPtr xpath;
319
+ xmlChar *query;
320
+
321
+ Data_Get_Struct(self, xmlXPathContext, ctx);
322
+
323
+ if (rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) {
324
+ xpath_handler = Qnil;
325
+ }
326
+
327
+ query = (xmlChar *)StringValueCStr(search_path);
328
+
329
+ if (Qnil != xpath_handler) {
330
+ /* FIXME: not sure if this is the correct place to shove private data. */
331
+ ctx->userData = (void *)xpath_handler;
332
+ xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler);
333
+ }
334
+
335
+ xmlResetLastError();
336
+ xmlSetStructuredErrorFunc(NULL, Nokogiri_error_raise);
337
+
338
+ /* For some reason, xmlXPathEvalExpression will blow up with a generic error */
339
+ /* when there is a non existent function. */
340
+ xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
341
+
342
+ xpath = xmlXPathEvalExpression(query, ctx);
343
+ xmlSetStructuredErrorFunc(NULL, NULL);
344
+ xmlSetGenericErrorFunc(NULL, NULL);
345
+
346
+ if (xpath == NULL) {
347
+ xmlErrorPtr error = xmlGetLastError();
348
+ rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
349
+ }
350
+
351
+ retval = xpath2ruby(xpath, ctx);
352
+ if (retval == Qundef) {
353
+ retval = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(ctx->doc));
354
+ }
355
+
356
+ xmlXPathFreeNodeSetList(xpath);
357
+
358
+ return retval;
359
+ }
360
+
361
+ /*
362
+ * call-seq:
363
+ * new(node)
364
+ *
365
+ * Create a new XPathContext with +node+ as the reference point.
366
+ */
367
+ static VALUE
368
+ new (VALUE klass, VALUE nodeobj)
369
+ {
370
+ xmlNodePtr node;
371
+ xmlXPathContextPtr ctx;
372
+ VALUE self;
373
+
374
+ Data_Get_Struct(nodeobj, xmlNode, node);
375
+
376
+ xmlXPathInit();
377
+
378
+ ctx = xmlXPathNewContext(node->doc);
379
+ ctx->node = node;
380
+
381
+ xmlXPathRegisterNs(ctx, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
382
+ xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
383
+ xpath_builtin_css_class);
384
+ xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
385
+ xpath_builtin_local_name_is);
386
+
387
+ self = Data_Wrap_Struct(klass, 0, deallocate, ctx);
388
+ return self;
389
+ }
390
+
391
+ void
392
+ noko_init_xml_xpath_context(void)
393
+ {
394
+ /*
395
+ * XPathContext is the entry point for searching a Document by using XPath.
396
+ */
397
+ cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
398
+
399
+ rb_undef_alloc_func(cNokogiriXmlXpathContext);
400
+
401
+ rb_define_singleton_method(cNokogiriXmlXpathContext, "new", new, 1);
402
+
403
+ rb_define_method(cNokogiriXmlXpathContext, "evaluate", evaluate, -1);
404
+ rb_define_method(cNokogiriXmlXpathContext, "register_variable", register_variable, 2);
405
+ rb_define_method(cNokogiriXmlXpathContext, "register_ns", register_ns, 2);
406
+ }