nokogiri 1.10.7 → 1.16.0
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.
- checksums.yaml +4 -4
- data/Gemfile +42 -0
- data/LICENSE-DEPENDENCIES.md +1632 -1022
- data/LICENSE.md +1 -1
- data/README.md +188 -96
- data/bin/nokogiri +63 -50
- data/dependencies.yml +34 -66
- data/ext/nokogiri/depend +38 -358
- data/ext/nokogiri/extconf.rb +862 -421
- data/ext/nokogiri/gumbo.c +594 -0
- data/ext/nokogiri/html4_document.c +165 -0
- data/ext/nokogiri/html4_element_description.c +299 -0
- data/ext/nokogiri/html4_entity_lookup.c +37 -0
- data/ext/nokogiri/html4_sax_parser_context.c +108 -0
- data/ext/nokogiri/html4_sax_push_parser.c +95 -0
- data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
- data/ext/nokogiri/nokogiri.c +251 -105
- data/ext/nokogiri/nokogiri.h +222 -90
- data/ext/nokogiri/test_global_handlers.c +40 -0
- data/ext/nokogiri/xml_attr.c +17 -17
- data/ext/nokogiri/xml_attribute_decl.c +22 -22
- data/ext/nokogiri/xml_cdata.c +39 -31
- data/ext/nokogiri/xml_comment.c +20 -27
- data/ext/nokogiri/xml_document.c +408 -243
- data/ext/nokogiri/xml_document_fragment.c +13 -17
- data/ext/nokogiri/xml_dtd.c +64 -58
- data/ext/nokogiri/xml_element_content.c +63 -55
- data/ext/nokogiri/xml_element_decl.c +31 -31
- data/ext/nokogiri/xml_encoding_handler.c +54 -21
- data/ext/nokogiri/xml_entity_decl.c +37 -35
- data/ext/nokogiri/xml_entity_reference.c +17 -19
- data/ext/nokogiri/xml_namespace.c +131 -61
- data/ext/nokogiri/xml_node.c +1343 -674
- data/ext/nokogiri/xml_node_set.c +246 -216
- data/ext/nokogiri/xml_processing_instruction.c +18 -20
- data/ext/nokogiri/xml_reader.c +305 -213
- data/ext/nokogiri/xml_relax_ng.c +87 -78
- data/ext/nokogiri/xml_sax_parser.c +149 -124
- data/ext/nokogiri/xml_sax_parser_context.c +149 -103
- data/ext/nokogiri/xml_sax_push_parser.c +65 -37
- data/ext/nokogiri/xml_schema.c +138 -82
- data/ext/nokogiri/xml_syntax_error.c +42 -21
- data/ext/nokogiri/xml_text.c +35 -26
- data/ext/nokogiri/xml_xpath_context.c +363 -178
- data/ext/nokogiri/xslt_stylesheet.c +335 -189
- data/gumbo-parser/CHANGES.md +63 -0
- data/gumbo-parser/Makefile +126 -0
- data/gumbo-parser/THANKS +27 -0
- data/gumbo-parser/src/Makefile +34 -0
- data/gumbo-parser/src/README.md +41 -0
- data/gumbo-parser/src/ascii.c +75 -0
- data/gumbo-parser/src/ascii.h +115 -0
- data/gumbo-parser/src/attribute.c +42 -0
- data/gumbo-parser/src/attribute.h +17 -0
- data/gumbo-parser/src/char_ref.c +22225 -0
- data/gumbo-parser/src/char_ref.h +29 -0
- data/gumbo-parser/src/char_ref.rl +2154 -0
- data/gumbo-parser/src/error.c +630 -0
- data/gumbo-parser/src/error.h +148 -0
- data/gumbo-parser/src/foreign_attrs.c +103 -0
- data/gumbo-parser/src/foreign_attrs.gperf +27 -0
- data/gumbo-parser/src/insertion_mode.h +33 -0
- data/gumbo-parser/src/macros.h +91 -0
- data/gumbo-parser/src/nokogiri_gumbo.h +944 -0
- data/gumbo-parser/src/parser.c +4891 -0
- data/gumbo-parser/src/parser.h +41 -0
- data/gumbo-parser/src/replacement.h +33 -0
- data/gumbo-parser/src/string_buffer.c +103 -0
- data/gumbo-parser/src/string_buffer.h +68 -0
- data/gumbo-parser/src/string_piece.c +48 -0
- data/gumbo-parser/src/svg_attrs.c +174 -0
- data/gumbo-parser/src/svg_attrs.gperf +77 -0
- data/gumbo-parser/src/svg_tags.c +137 -0
- data/gumbo-parser/src/svg_tags.gperf +55 -0
- data/gumbo-parser/src/tag.c +223 -0
- data/gumbo-parser/src/tag_lookup.c +382 -0
- data/gumbo-parser/src/tag_lookup.gperf +170 -0
- data/gumbo-parser/src/tag_lookup.h +13 -0
- data/gumbo-parser/src/token_buffer.c +79 -0
- data/gumbo-parser/src/token_buffer.h +71 -0
- data/gumbo-parser/src/token_type.h +17 -0
- data/gumbo-parser/src/tokenizer.c +3464 -0
- data/gumbo-parser/src/tokenizer.h +112 -0
- data/gumbo-parser/src/tokenizer_states.h +339 -0
- data/gumbo-parser/src/utf8.c +245 -0
- data/gumbo-parser/src/utf8.h +164 -0
- data/gumbo-parser/src/util.c +66 -0
- data/gumbo-parser/src/util.h +34 -0
- data/gumbo-parser/src/vector.c +111 -0
- data/gumbo-parser/src/vector.h +45 -0
- data/lib/nokogiri/class_resolver.rb +67 -0
- data/lib/nokogiri/css/node.rb +10 -8
- data/lib/nokogiri/css/parser.rb +397 -377
- data/lib/nokogiri/css/parser.y +250 -245
- data/lib/nokogiri/css/parser_extras.rb +54 -49
- data/lib/nokogiri/css/syntax_error.rb +3 -1
- data/lib/nokogiri/css/tokenizer.rb +5 -3
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +205 -96
- data/lib/nokogiri/css.rb +56 -17
- data/lib/nokogiri/decorators/slop.rb +9 -7
- data/lib/nokogiri/encoding_handler.rb +57 -0
- data/lib/nokogiri/extension.rb +32 -0
- data/lib/nokogiri/gumbo.rb +15 -0
- data/lib/nokogiri/html.rb +38 -27
- data/lib/nokogiri/{html → html4}/builder.rb +4 -2
- data/lib/nokogiri/html4/document.rb +214 -0
- data/lib/nokogiri/html4/document_fragment.rb +54 -0
- data/lib/nokogiri/{html → html4}/element_description.rb +3 -1
- data/lib/nokogiri/html4/element_description_defaults.rb +2040 -0
- data/lib/nokogiri/html4/encoding_reader.rb +121 -0
- data/lib/nokogiri/{html → html4}/entity_lookup.rb +4 -2
- data/lib/nokogiri/{html → html4}/sax/parser.rb +17 -16
- data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
- data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
- data/lib/nokogiri/html4.rb +47 -0
- data/lib/nokogiri/html5/document.rb +168 -0
- data/lib/nokogiri/html5/document_fragment.rb +90 -0
- data/lib/nokogiri/html5/node.rb +103 -0
- data/lib/nokogiri/html5.rb +326 -0
- data/lib/nokogiri/jruby/dependencies.rb +3 -0
- data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
- data/lib/nokogiri/syntax_error.rb +2 -0
- data/lib/nokogiri/version/constant.rb +6 -0
- data/lib/nokogiri/version/info.rb +224 -0
- data/lib/nokogiri/version.rb +3 -108
- data/lib/nokogiri/xml/attr.rb +55 -3
- data/lib/nokogiri/xml/attribute_decl.rb +6 -2
- data/lib/nokogiri/xml/builder.rb +75 -34
- data/lib/nokogiri/xml/cdata.rb +3 -1
- data/lib/nokogiri/xml/character_data.rb +2 -0
- data/lib/nokogiri/xml/document.rb +312 -127
- data/lib/nokogiri/xml/document_fragment.rb +93 -48
- data/lib/nokogiri/xml/dtd.rb +4 -2
- data/lib/nokogiri/xml/element_content.rb +12 -2
- data/lib/nokogiri/xml/element_decl.rb +6 -2
- data/lib/nokogiri/xml/entity_decl.rb +7 -3
- data/lib/nokogiri/xml/entity_reference.rb +2 -0
- data/lib/nokogiri/xml/namespace.rb +44 -0
- data/lib/nokogiri/xml/node/save_options.rb +23 -8
- data/lib/nokogiri/xml/node.rb +1096 -419
- data/lib/nokogiri/xml/node_set.rb +137 -61
- data/lib/nokogiri/xml/notation.rb +13 -0
- data/lib/nokogiri/xml/parse_options.rb +145 -52
- data/lib/nokogiri/xml/pp/character_data.rb +9 -6
- data/lib/nokogiri/xml/pp/node.rb +42 -30
- data/lib/nokogiri/xml/pp.rb +4 -2
- data/lib/nokogiri/xml/processing_instruction.rb +4 -1
- data/lib/nokogiri/xml/reader.rb +21 -28
- data/lib/nokogiri/xml/relax_ng.rb +8 -2
- data/lib/nokogiri/xml/sax/document.rb +45 -49
- data/lib/nokogiri/xml/sax/parser.rb +39 -36
- data/lib/nokogiri/xml/sax/parser_context.rb +8 -3
- data/lib/nokogiri/xml/sax/push_parser.rb +6 -5
- data/lib/nokogiri/xml/sax.rb +6 -4
- data/lib/nokogiri/xml/schema.rb +19 -9
- data/lib/nokogiri/xml/searchable.rb +120 -72
- data/lib/nokogiri/xml/syntax_error.rb +7 -5
- data/lib/nokogiri/xml/text.rb +2 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
- data/lib/nokogiri/xml/xpath.rb +15 -4
- data/lib/nokogiri/xml/xpath_context.rb +3 -3
- data/lib/nokogiri/xml.rb +39 -38
- data/lib/nokogiri/xslt/stylesheet.rb +3 -1
- data/lib/nokogiri/xslt.rb +101 -22
- data/lib/nokogiri.rb +59 -75
- data/lib/xsd/xmlparser/nokogiri.rb +29 -25
- data/patches/libxml2/{0004-libxml2.la-is-in-top_builddir.patch → 0003-libxml2.la-is-in-top_builddir.patch} +1 -1
- data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
- data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
- data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
- data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
- data/ports/archives/libxml2-2.12.3.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.39.tar.xz +0 -0
- metadata +121 -291
- data/ext/nokogiri/html_document.c +0 -170
- data/ext/nokogiri/html_document.h +0 -10
- data/ext/nokogiri/html_element_description.c +0 -279
- data/ext/nokogiri/html_element_description.h +0 -10
- data/ext/nokogiri/html_entity_lookup.c +0 -32
- data/ext/nokogiri/html_entity_lookup.h +0 -8
- data/ext/nokogiri/html_sax_parser_context.c +0 -116
- data/ext/nokogiri/html_sax_parser_context.h +0 -11
- data/ext/nokogiri/html_sax_push_parser.c +0 -87
- data/ext/nokogiri/html_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_attr.h +0 -9
- data/ext/nokogiri/xml_attribute_decl.h +0 -9
- data/ext/nokogiri/xml_cdata.h +0 -9
- data/ext/nokogiri/xml_comment.h +0 -9
- data/ext/nokogiri/xml_document.h +0 -23
- data/ext/nokogiri/xml_document_fragment.h +0 -10
- data/ext/nokogiri/xml_dtd.h +0 -10
- data/ext/nokogiri/xml_element_content.h +0 -10
- data/ext/nokogiri/xml_element_decl.h +0 -9
- data/ext/nokogiri/xml_encoding_handler.h +0 -8
- data/ext/nokogiri/xml_entity_decl.h +0 -10
- data/ext/nokogiri/xml_entity_reference.h +0 -9
- data/ext/nokogiri/xml_io.c +0 -61
- data/ext/nokogiri/xml_io.h +0 -11
- data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
- data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
- data/ext/nokogiri/xml_namespace.h +0 -14
- data/ext/nokogiri/xml_node.h +0 -13
- data/ext/nokogiri/xml_node_set.h +0 -12
- data/ext/nokogiri/xml_processing_instruction.h +0 -9
- data/ext/nokogiri/xml_reader.h +0 -10
- data/ext/nokogiri/xml_relax_ng.h +0 -9
- data/ext/nokogiri/xml_sax_parser.h +0 -39
- data/ext/nokogiri/xml_sax_parser_context.h +0 -10
- data/ext/nokogiri/xml_sax_push_parser.h +0 -9
- data/ext/nokogiri/xml_schema.h +0 -9
- data/ext/nokogiri/xml_syntax_error.h +0 -13
- data/ext/nokogiri/xml_text.h +0 -9
- data/ext/nokogiri/xml_xpath_context.h +0 -10
- data/ext/nokogiri/xslt_stylesheet.h +0 -14
- data/lib/nokogiri/html/document.rb +0 -335
- data/lib/nokogiri/html/document_fragment.rb +0 -49
- data/lib/nokogiri/html/element_description_defaults.rb +0 -671
- data/lib/nokogiri/html/sax/parser_context.rb +0 -16
- data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
- data/ports/archives/libxml2-2.9.10.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
- /data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
- /data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
@@ -1,298 +1,483 @@
|
|
1
|
-
#include <
|
1
|
+
#include <nokogiri.h>
|
2
2
|
|
3
|
-
|
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_PREFIX = (const xmlChar *)"nokogiri";
|
10
|
+
static const xmlChar *NOKOGIRI_URI = (const xmlChar *)"http://www.nokogiri.org/default_ns/ruby/extensions_functions";
|
11
|
+
static const xmlChar *NOKOGIRI_BUILTIN_PREFIX = (const xmlChar *)"nokogiri-builtin";
|
12
|
+
static const xmlChar *NOKOGIRI_BUILTIN_URI = (const xmlChar *)"https://www.nokogiri.org/default_ns/ruby/builtins";
|
4
13
|
|
5
|
-
static void
|
14
|
+
static void
|
15
|
+
xml_xpath_context_deallocate(void *data)
|
6
16
|
{
|
7
|
-
|
8
|
-
xmlXPathFreeContext(
|
9
|
-
NOKOGIRI_DEBUG_END(ctx);
|
17
|
+
xmlXPathContextPtr c_context = data;
|
18
|
+
xmlXPathFreeContext(c_context);
|
10
19
|
}
|
11
20
|
|
21
|
+
static const rb_data_type_t xml_xpath_context_type = {
|
22
|
+
.wrap_struct_name = "Nokogiri::XML::XPathContext",
|
23
|
+
.function = {
|
24
|
+
.dfree = xml_xpath_context_deallocate,
|
25
|
+
},
|
26
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
27
|
+
};
|
28
|
+
|
29
|
+
/* find a CSS class in an HTML element's `class` attribute */
|
30
|
+
static const xmlChar *
|
31
|
+
builtin_css_class(const xmlChar *str, const xmlChar *val)
|
32
|
+
{
|
33
|
+
int val_len;
|
34
|
+
|
35
|
+
if (str == NULL) { return (NULL); }
|
36
|
+
if (val == NULL) { return (NULL); }
|
37
|
+
|
38
|
+
val_len = xmlStrlen(val);
|
39
|
+
if (val_len == 0) { return (str); }
|
40
|
+
|
41
|
+
while (*str != 0) {
|
42
|
+
if ((*str == *val) && !xmlStrncmp(str, val, val_len)) {
|
43
|
+
const xmlChar *next_byte = str + val_len;
|
44
|
+
|
45
|
+
/* only match if the next byte is whitespace or end of string */
|
46
|
+
if ((*next_byte == 0) || (IS_BLANK_CH(*next_byte))) {
|
47
|
+
return ((const xmlChar *)str);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
/* advance str to whitespace */
|
52
|
+
while ((*str != 0) && !IS_BLANK_CH(*str)) {
|
53
|
+
str++;
|
54
|
+
}
|
55
|
+
|
56
|
+
/* advance str to start of next word or end of string */
|
57
|
+
while ((*str != 0) && IS_BLANK_CH(*str)) {
|
58
|
+
str++;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
return (NULL);
|
63
|
+
}
|
64
|
+
|
65
|
+
/* xmlXPathFunction to wrap builtin_css_class() */
|
66
|
+
static void
|
67
|
+
xpath_builtin_css_class(xmlXPathParserContextPtr ctxt, int nargs)
|
68
|
+
{
|
69
|
+
xmlXPathObjectPtr hay, needle;
|
70
|
+
|
71
|
+
CHECK_ARITY(2);
|
72
|
+
|
73
|
+
CAST_TO_STRING;
|
74
|
+
needle = valuePop(ctxt);
|
75
|
+
if ((needle == NULL) || (needle->type != XPATH_STRING)) {
|
76
|
+
xmlXPathFreeObject(needle);
|
77
|
+
XP_ERROR(XPATH_INVALID_TYPE);
|
78
|
+
}
|
79
|
+
|
80
|
+
CAST_TO_STRING;
|
81
|
+
hay = valuePop(ctxt);
|
82
|
+
if ((hay == NULL) || (hay->type != XPATH_STRING)) {
|
83
|
+
xmlXPathFreeObject(hay);
|
84
|
+
xmlXPathFreeObject(needle);
|
85
|
+
XP_ERROR(XPATH_INVALID_TYPE);
|
86
|
+
}
|
87
|
+
|
88
|
+
if (builtin_css_class(hay->stringval, needle->stringval)) {
|
89
|
+
valuePush(ctxt, xmlXPathNewBoolean(1));
|
90
|
+
} else {
|
91
|
+
valuePush(ctxt, xmlXPathNewBoolean(0));
|
92
|
+
}
|
93
|
+
|
94
|
+
xmlXPathFreeObject(hay);
|
95
|
+
xmlXPathFreeObject(needle);
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
/* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should
|
100
|
+
* ignore namespaces */
|
101
|
+
static void
|
102
|
+
xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
|
103
|
+
{
|
104
|
+
xmlXPathObjectPtr element_name;
|
105
|
+
|
106
|
+
assert(ctxt->context->node);
|
107
|
+
|
108
|
+
CHECK_ARITY(1);
|
109
|
+
CAST_TO_STRING;
|
110
|
+
CHECK_TYPE(XPATH_STRING);
|
111
|
+
element_name = valuePop(ctxt);
|
112
|
+
|
113
|
+
valuePush(
|
114
|
+
ctxt,
|
115
|
+
xmlXPathNewBoolean(xmlStrEqual(ctxt->context->node->name, element_name->stringval))
|
116
|
+
);
|
117
|
+
|
118
|
+
xmlXPathFreeObject(element_name);
|
119
|
+
}
|
120
|
+
|
121
|
+
|
12
122
|
/*
|
13
123
|
* call-seq:
|
14
|
-
*
|
124
|
+
* register_ns(prefix, uri) → Nokogiri::XML::XPathContext
|
15
125
|
*
|
16
|
-
* Register the namespace with +prefix+ and +uri
|
126
|
+
* Register the namespace with +prefix+ and +uri+ for use in future queries.
|
127
|
+
*
|
128
|
+
* [Returns] +self+
|
17
129
|
*/
|
18
|
-
static VALUE
|
130
|
+
static VALUE
|
131
|
+
rb_xml_xpath_context_register_ns(VALUE rb_context, VALUE prefix, VALUE uri)
|
19
132
|
{
|
20
|
-
xmlXPathContextPtr
|
21
|
-
Data_Get_Struct(self, xmlXPathContext, ctx);
|
133
|
+
xmlXPathContextPtr c_context;
|
22
134
|
|
23
|
-
|
24
|
-
|
25
|
-
|
135
|
+
TypedData_Get_Struct(
|
136
|
+
rb_context,
|
137
|
+
xmlXPathContext,
|
138
|
+
&xml_xpath_context_type,
|
139
|
+
c_context
|
26
140
|
);
|
27
|
-
|
141
|
+
|
142
|
+
xmlXPathRegisterNs(c_context,
|
143
|
+
(const xmlChar *)StringValueCStr(prefix),
|
144
|
+
(const xmlChar *)StringValueCStr(uri)
|
145
|
+
);
|
146
|
+
return rb_context;
|
28
147
|
}
|
29
148
|
|
30
149
|
/*
|
31
150
|
* call-seq:
|
32
|
-
*
|
151
|
+
* register_variable(name, value) → Nokogiri::XML::XPathContext
|
152
|
+
*
|
153
|
+
* Register the variable +name+ with +value+ for use in future queries.
|
33
154
|
*
|
34
|
-
*
|
155
|
+
* [Returns] +self+
|
35
156
|
*/
|
36
|
-
static VALUE
|
157
|
+
static VALUE
|
158
|
+
rb_xml_xpath_context_register_variable(VALUE rb_context, VALUE name, VALUE value)
|
37
159
|
{
|
38
|
-
|
39
|
-
|
40
|
-
|
160
|
+
xmlXPathContextPtr c_context;
|
161
|
+
xmlXPathObjectPtr xmlValue;
|
162
|
+
|
163
|
+
TypedData_Get_Struct(
|
164
|
+
rb_context,
|
165
|
+
xmlXPathContext,
|
166
|
+
&xml_xpath_context_type,
|
167
|
+
c_context
|
168
|
+
);
|
41
169
|
|
42
|
-
|
170
|
+
xmlValue = xmlXPathNewCString(StringValueCStr(value));
|
43
171
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
172
|
+
xmlXPathRegisterVariable(
|
173
|
+
c_context,
|
174
|
+
(const xmlChar *)StringValueCStr(name),
|
175
|
+
xmlValue
|
176
|
+
);
|
48
177
|
|
49
|
-
|
178
|
+
return rb_context;
|
50
179
|
}
|
51
180
|
|
52
|
-
|
181
|
+
|
182
|
+
/*
|
183
|
+
* convert an XPath object into a Ruby object of the appropriate type.
|
184
|
+
* returns Qundef if no conversion was possible.
|
185
|
+
*/
|
186
|
+
static VALUE
|
187
|
+
xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr c_context)
|
53
188
|
{
|
54
|
-
|
55
|
-
|
189
|
+
VALUE rb_retval;
|
190
|
+
|
191
|
+
assert(c_context->doc);
|
192
|
+
assert(DOC_RUBY_OBJECT_TEST(c_context->doc));
|
193
|
+
|
194
|
+
switch (c_xpath_object->type) {
|
195
|
+
case XPATH_STRING:
|
196
|
+
rb_retval = NOKOGIRI_STR_NEW2(c_xpath_object->stringval);
|
197
|
+
xmlFree(c_xpath_object->stringval);
|
198
|
+
return rb_retval;
|
199
|
+
|
200
|
+
case XPATH_NODESET:
|
201
|
+
return noko_xml_node_set_wrap(
|
202
|
+
c_xpath_object->nodesetval,
|
203
|
+
DOC_RUBY_OBJECT(c_context->doc)
|
204
|
+
);
|
205
|
+
|
206
|
+
case XPATH_NUMBER:
|
207
|
+
return rb_float_new(c_xpath_object->floatval);
|
208
|
+
|
209
|
+
case XPATH_BOOLEAN:
|
210
|
+
return (c_xpath_object->boolval == 1) ? Qtrue : Qfalse;
|
211
|
+
|
212
|
+
default:
|
213
|
+
return Qundef;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
void
|
218
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(
|
219
|
+
xmlXPathParserContextPtr ctxt,
|
220
|
+
int argc,
|
221
|
+
VALUE rb_xpath_handler,
|
222
|
+
const char *method_name
|
223
|
+
)
|
224
|
+
{
|
225
|
+
VALUE rb_retval;
|
56
226
|
VALUE *argv;
|
57
|
-
VALUE
|
58
|
-
xmlNodeSetPtr
|
59
|
-
xmlXPathObjectPtr
|
227
|
+
VALUE rb_node_set = Qnil;
|
228
|
+
xmlNodeSetPtr c_node_set = NULL;
|
229
|
+
xmlXPathObjectPtr c_xpath_object;
|
60
230
|
|
61
|
-
assert(
|
62
|
-
assert(DOC_RUBY_OBJECT_TEST(
|
231
|
+
assert(ctxt->context->doc);
|
232
|
+
assert(DOC_RUBY_OBJECT_TEST(ctxt->context->doc));
|
63
233
|
|
64
|
-
argv = (VALUE *)
|
65
|
-
for (
|
66
|
-
rb_gc_register_address(&argv[
|
234
|
+
argv = (VALUE *)ruby_xcalloc((size_t)argc, sizeof(VALUE));
|
235
|
+
for (int j = 0 ; j < argc ; ++j) {
|
236
|
+
rb_gc_register_address(&argv[j]);
|
67
237
|
}
|
68
238
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
case XPATH_STRING:
|
77
|
-
argv[i] = NOKOGIRI_STR_NEW2(obj->stringval);
|
78
|
-
break;
|
79
|
-
case XPATH_BOOLEAN:
|
80
|
-
argv[i] = obj->boolval == 1 ? Qtrue : Qfalse;
|
81
|
-
break;
|
82
|
-
case XPATH_NUMBER:
|
83
|
-
argv[i] = rb_float_new(obj->floatval);
|
84
|
-
break;
|
85
|
-
case XPATH_NODESET:
|
86
|
-
argv[i] = Nokogiri_wrap_xml_node_set(obj->nodesetval, doc);
|
87
|
-
break;
|
88
|
-
default:
|
89
|
-
argv[i] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj));
|
90
|
-
}
|
91
|
-
xmlXPathFreeNodeSetList(obj);
|
92
|
-
} while(i-- > 0);
|
239
|
+
for (int j = argc - 1 ; j >= 0 ; --j) {
|
240
|
+
c_xpath_object = valuePop(ctxt);
|
241
|
+
argv[j] = xpath2ruby(c_xpath_object, ctxt->context);
|
242
|
+
if (argv[j] == Qundef) {
|
243
|
+
argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(c_xpath_object));
|
244
|
+
}
|
245
|
+
xmlXPathFreeNodeSetList(c_xpath_object);
|
93
246
|
}
|
94
247
|
|
95
|
-
|
248
|
+
rb_retval = rb_funcall2(
|
249
|
+
rb_xpath_handler,
|
250
|
+
rb_intern((const char *)method_name),
|
251
|
+
argc,
|
252
|
+
argv
|
253
|
+
);
|
96
254
|
|
97
|
-
for (
|
98
|
-
rb_gc_unregister_address(&argv[
|
255
|
+
for (int j = 0 ; j < argc ; ++j) {
|
256
|
+
rb_gc_unregister_address(&argv[j]);
|
99
257
|
}
|
100
|
-
|
258
|
+
ruby_xfree(argv);
|
101
259
|
|
102
|
-
switch(TYPE(
|
260
|
+
switch (TYPE(rb_retval)) {
|
103
261
|
case T_FLOAT:
|
104
262
|
case T_BIGNUM:
|
105
263
|
case T_FIXNUM:
|
106
|
-
xmlXPathReturnNumber(
|
264
|
+
xmlXPathReturnNumber(ctxt, NUM2DBL(rb_retval));
|
107
265
|
break;
|
108
266
|
case T_STRING:
|
109
|
-
xmlXPathReturnString(
|
110
|
-
ctx,
|
111
|
-
xmlCharStrdup(StringValueCStr(result))
|
112
|
-
);
|
267
|
+
xmlXPathReturnString(ctxt, xmlCharStrdup(StringValueCStr(rb_retval)));
|
113
268
|
break;
|
114
269
|
case T_TRUE:
|
115
|
-
xmlXPathReturnTrue(
|
270
|
+
xmlXPathReturnTrue(ctxt);
|
116
271
|
break;
|
117
272
|
case T_FALSE:
|
118
|
-
xmlXPathReturnFalse(
|
273
|
+
xmlXPathReturnFalse(ctxt);
|
119
274
|
break;
|
120
275
|
case T_NIL:
|
121
276
|
break;
|
122
|
-
case T_ARRAY:
|
123
|
-
{
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
Data_Get_Struct(node_set, xmlNodeSet, xml_node_set);
|
129
|
-
xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
|
130
|
-
}
|
277
|
+
case T_ARRAY: {
|
278
|
+
VALUE construct_args[2] = { DOC_RUBY_OBJECT(ctxt->context->doc), rb_retval };
|
279
|
+
rb_node_set = rb_class_new_instance(2, construct_args, cNokogiriXmlNodeSet);
|
280
|
+
c_node_set = noko_xml_node_set_unwrap(rb_node_set);
|
281
|
+
xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
|
282
|
+
}
|
131
283
|
break;
|
132
284
|
case T_DATA:
|
133
|
-
if(rb_obj_is_kind_of(
|
134
|
-
|
285
|
+
if (rb_obj_is_kind_of(rb_retval, cNokogiriXmlNodeSet)) {
|
286
|
+
c_node_set = noko_xml_node_set_unwrap(rb_retval);
|
135
287
|
/* Copy the node set, otherwise it will get GC'd. */
|
136
|
-
xmlXPathReturnNodeSet(
|
288
|
+
xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
|
137
289
|
break;
|
138
290
|
}
|
139
291
|
default:
|
140
292
|
rb_raise(rb_eRuntimeError, "Invalid return type");
|
141
|
-
|
293
|
+
}
|
142
294
|
}
|
143
295
|
|
144
|
-
static void
|
296
|
+
static void
|
297
|
+
method_caller(xmlXPathParserContextPtr ctxt, int argc)
|
145
298
|
{
|
146
|
-
VALUE
|
147
|
-
const char *
|
148
|
-
|
149
|
-
assert(
|
150
|
-
assert(
|
151
|
-
assert(
|
152
|
-
assert(
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
Nokogiri_marshal_xpath_funcall_and_return_values(
|
299
|
+
VALUE rb_xpath_handler = Qnil;
|
300
|
+
const char *method_name = NULL ;
|
301
|
+
|
302
|
+
assert(ctxt);
|
303
|
+
assert(ctxt->context);
|
304
|
+
assert(ctxt->context->userData);
|
305
|
+
assert(ctxt->context->function);
|
306
|
+
|
307
|
+
rb_xpath_handler = (VALUE)(ctxt->context->userData);
|
308
|
+
method_name = (const char *)(ctxt->context->function);
|
309
|
+
|
310
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(
|
311
|
+
ctxt,
|
312
|
+
argc,
|
313
|
+
rb_xpath_handler,
|
314
|
+
method_name
|
315
|
+
);
|
158
316
|
}
|
159
317
|
|
160
|
-
static xmlXPathFunction
|
161
|
-
|
162
|
-
const xmlChar* ns_uri )
|
318
|
+
static xmlXPathFunction
|
319
|
+
handler_lookup(void *data, const xmlChar *c_name, const xmlChar *c_ns_uri)
|
163
320
|
{
|
164
|
-
VALUE
|
165
|
-
if(rb_respond_to(
|
166
|
-
|
321
|
+
VALUE rb_handler = (VALUE)data;
|
322
|
+
if (rb_respond_to(rb_handler, rb_intern((const char *)c_name))) {
|
323
|
+
if (c_ns_uri == NULL) {
|
324
|
+
NOKO_WARN_DEPRECATION("A custom XPath or CSS handler function named '%s' is being invoked without a namespace. Please update your query to reference this function as 'nokogiri:%s'. Invoking custom handler functions without a namespace is deprecated and will become an error in Nokogiri v1.17.0.",
|
325
|
+
c_name, c_name); // deprecated in v1.15.0, remove in v1.17.0
|
326
|
+
}
|
327
|
+
return method_caller;
|
328
|
+
}
|
167
329
|
|
168
330
|
return NULL;
|
169
331
|
}
|
170
332
|
|
171
|
-
|
172
|
-
static void
|
333
|
+
PRINTFLIKE_DECL(2, 3)
|
334
|
+
static void
|
335
|
+
generic_exception_pusher(void *data, const char *msg, ...)
|
173
336
|
{
|
174
|
-
|
337
|
+
VALUE rb_errors = (VALUE)data;
|
338
|
+
VALUE rb_message;
|
339
|
+
VALUE rb_exception;
|
340
|
+
|
341
|
+
Check_Type(rb_errors, T_ARRAY);
|
175
342
|
|
343
|
+
#ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
|
344
|
+
/* It is not currently possible to pass var args from native
|
345
|
+
functions to sulong, so we work around the issue here. */
|
346
|
+
rb_message = rb_sprintf("generic_exception_pusher: %s", msg);
|
347
|
+
#else
|
176
348
|
va_list args;
|
177
349
|
va_start(args, msg);
|
178
|
-
|
350
|
+
rb_message = rb_vsprintf(msg, args);
|
179
351
|
va_end(args);
|
352
|
+
#endif
|
180
353
|
|
181
|
-
|
354
|
+
rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
|
355
|
+
rb_ary_push(rb_errors, rb_exception);
|
182
356
|
}
|
183
357
|
|
184
358
|
/*
|
185
359
|
* call-seq:
|
186
|
-
*
|
360
|
+
* evaluate(search_path, handler = nil) → Object
|
187
361
|
*
|
188
|
-
* Evaluate the +search_path+
|
362
|
+
* Evaluate the +search_path+ query.
|
363
|
+
*
|
364
|
+
* [Returns] an object of the appropriate type for the query, which could be +NodeSet+, a +String+,
|
365
|
+
* a +Float+, or a boolean.
|
189
366
|
*/
|
190
|
-
static VALUE
|
367
|
+
static VALUE
|
368
|
+
rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
|
191
369
|
{
|
192
370
|
VALUE search_path, xpath_handler;
|
193
|
-
VALUE
|
194
|
-
xmlXPathContextPtr
|
371
|
+
VALUE retval = Qnil;
|
372
|
+
xmlXPathContextPtr c_context;
|
195
373
|
xmlXPathObjectPtr xpath;
|
196
374
|
xmlChar *query;
|
375
|
+
VALUE errors = rb_ary_new();
|
197
376
|
|
198
|
-
|
377
|
+
TypedData_Get_Struct(
|
378
|
+
rb_context,
|
379
|
+
xmlXPathContext,
|
380
|
+
&xml_xpath_context_type,
|
381
|
+
c_context
|
382
|
+
);
|
199
383
|
|
200
|
-
if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1)
|
384
|
+
if (rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) {
|
201
385
|
xpath_handler = Qnil;
|
386
|
+
}
|
202
387
|
|
203
388
|
query = (xmlChar *)StringValueCStr(search_path);
|
204
389
|
|
205
|
-
if(Qnil != xpath_handler) {
|
390
|
+
if (Qnil != xpath_handler) {
|
206
391
|
/* FIXME: not sure if this is the correct place to shove private data. */
|
207
|
-
|
208
|
-
xmlXPathRegisterFuncLookup(
|
392
|
+
c_context->userData = (void *)xpath_handler;
|
393
|
+
xmlXPathRegisterFuncLookup(
|
394
|
+
c_context,
|
395
|
+
handler_lookup,
|
396
|
+
(void *)xpath_handler
|
397
|
+
);
|
209
398
|
}
|
210
399
|
|
211
|
-
|
212
|
-
|
400
|
+
xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
|
401
|
+
xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
|
213
402
|
|
214
|
-
|
215
|
-
/* when there is a non existent function. */
|
216
|
-
xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
|
403
|
+
xpath = xmlXPathEvalExpression(query, c_context);
|
217
404
|
|
218
|
-
xpath = xmlXPathEvalExpression(query, ctx);
|
219
405
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
220
406
|
xmlSetGenericErrorFunc(NULL, NULL);
|
221
407
|
|
222
|
-
if(xpath == NULL) {
|
223
|
-
|
224
|
-
rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
|
408
|
+
if (xpath == NULL) {
|
409
|
+
rb_exc_raise(rb_ary_entry(errors, 0));
|
225
410
|
}
|
226
411
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
switch(xpath->type) {
|
231
|
-
case XPATH_STRING:
|
232
|
-
thing = NOKOGIRI_STR_NEW2(xpath->stringval);
|
233
|
-
xmlFree(xpath->stringval);
|
234
|
-
break;
|
235
|
-
case XPATH_NODESET:
|
236
|
-
thing = Nokogiri_wrap_xml_node_set(xpath->nodesetval,
|
237
|
-
DOC_RUBY_OBJECT(ctx->doc));
|
238
|
-
break;
|
239
|
-
case XPATH_NUMBER:
|
240
|
-
thing = rb_float_new(xpath->floatval);
|
241
|
-
break;
|
242
|
-
case XPATH_BOOLEAN:
|
243
|
-
thing = xpath->boolval == 1 ? Qtrue : Qfalse;
|
244
|
-
break;
|
245
|
-
default:
|
246
|
-
thing = Nokogiri_wrap_xml_node_set(NULL, DOC_RUBY_OBJECT(ctx->doc));
|
412
|
+
retval = xpath2ruby(xpath, c_context);
|
413
|
+
if (retval == Qundef) {
|
414
|
+
retval = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
|
247
415
|
}
|
248
416
|
|
249
417
|
xmlXPathFreeNodeSetList(xpath);
|
250
418
|
|
251
|
-
return
|
419
|
+
return retval;
|
252
420
|
}
|
253
421
|
|
254
422
|
/*
|
255
423
|
* call-seq:
|
256
|
-
*
|
424
|
+
* new(node)
|
257
425
|
*
|
258
|
-
* Create a new XPathContext with +node+ as the
|
426
|
+
* Create a new XPathContext with +node+ as the context node.
|
259
427
|
*/
|
260
|
-
static VALUE
|
428
|
+
static VALUE
|
429
|
+
rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
|
261
430
|
{
|
262
431
|
xmlNodePtr node;
|
263
|
-
xmlXPathContextPtr
|
264
|
-
VALUE
|
432
|
+
xmlXPathContextPtr c_context;
|
433
|
+
VALUE rb_context;
|
265
434
|
|
266
|
-
|
435
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, node);
|
267
436
|
|
268
|
-
|
437
|
+
#if LIBXML_VERSION < 21000
|
438
|
+
/* deprecated in 40483d0 */
|
439
|
+
xmlXPathInit();
|
440
|
+
#endif
|
441
|
+
|
442
|
+
c_context = xmlXPathNewContext(node->doc);
|
443
|
+
c_context->node = node;
|
444
|
+
|
445
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
446
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
|
447
|
+
xmlXPathRegisterFuncNS(
|
448
|
+
c_context,
|
449
|
+
(const xmlChar *)"css-class",
|
450
|
+
NOKOGIRI_BUILTIN_URI,
|
451
|
+
xpath_builtin_css_class
|
452
|
+
);
|
453
|
+
xmlXPathRegisterFuncNS(
|
454
|
+
c_context,
|
455
|
+
(const xmlChar *)"local-name-is",
|
456
|
+
NOKOGIRI_BUILTIN_URI,
|
457
|
+
xpath_builtin_local_name_is
|
458
|
+
);
|
269
459
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
460
|
+
rb_context = TypedData_Wrap_Struct(
|
461
|
+
klass,
|
462
|
+
&xml_xpath_context_type,
|
463
|
+
c_context
|
464
|
+
);
|
465
|
+
return rb_context;
|
275
466
|
}
|
276
467
|
|
277
|
-
|
278
|
-
|
468
|
+
void
|
469
|
+
noko_init_xml_xpath_context(void)
|
279
470
|
{
|
280
|
-
VALUE module = rb_define_module("Nokogiri");
|
281
|
-
|
282
471
|
/*
|
283
|
-
*
|
472
|
+
* XPathContext is the entry point for searching a +Document+ by using XPath.
|
284
473
|
*/
|
285
|
-
|
474
|
+
cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
|
286
475
|
|
287
|
-
|
288
|
-
* XPathContext is the entry point for searching a Document by using XPath.
|
289
|
-
*/
|
290
|
-
VALUE klass = rb_define_class_under(xml, "XPathContext", rb_cObject);
|
476
|
+
rb_undef_alloc_func(cNokogiriXmlXpathContext);
|
291
477
|
|
292
|
-
cNokogiriXmlXpathContext
|
478
|
+
rb_define_singleton_method(cNokogiriXmlXpathContext, "new", rb_xml_xpath_context_new, 1);
|
293
479
|
|
294
|
-
|
295
|
-
rb_define_method(
|
296
|
-
rb_define_method(
|
297
|
-
rb_define_method(klass, "register_ns", register_ns, 2);
|
480
|
+
rb_define_method(cNokogiriXmlXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
|
481
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
|
482
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
|
298
483
|
}
|