nokogiri 1.10.9 → 1.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nokogiri might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +38 -0
- data/LICENSE-DEPENDENCIES.md +1632 -1022
- data/LICENSE.md +1 -1
- data/README.md +190 -95
- data/bin/nokogiri +63 -50
- data/dependencies.yml +34 -66
- data/ext/nokogiri/depend +38 -358
- data/ext/nokogiri/extconf.rb +909 -422
- data/ext/nokogiri/gumbo.c +610 -0
- data/ext/nokogiri/html4_document.c +171 -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.c +40 -0
- data/ext/nokogiri/html4_sax_parser_context.c +98 -0
- data/ext/nokogiri/html4_sax_push_parser.c +96 -0
- data/ext/nokogiri/libxml2_polyfill.c +114 -0
- data/ext/nokogiri/nokogiri.c +258 -105
- data/ext/nokogiri/nokogiri.h +207 -90
- data/ext/nokogiri/test_global_handlers.c +40 -0
- data/ext/nokogiri/xml_attr.c +18 -18
- data/ext/nokogiri/xml_attribute_decl.c +22 -22
- data/ext/nokogiri/xml_cdata.c +33 -33
- data/ext/nokogiri/xml_comment.c +19 -31
- data/ext/nokogiri/xml_document.c +499 -323
- data/ext/nokogiri/xml_document_fragment.c +17 -36
- data/ext/nokogiri/xml_dtd.c +65 -59
- 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 +1429 -723
- data/ext/nokogiri/xml_node_set.c +257 -225
- data/ext/nokogiri/xml_processing_instruction.c +18 -20
- data/ext/nokogiri/xml_reader.c +340 -231
- data/ext/nokogiri/xml_relax_ng.c +87 -99
- data/ext/nokogiri/xml_sax_parser.c +269 -176
- data/ext/nokogiri/xml_sax_parser_context.c +286 -152
- data/ext/nokogiri/xml_sax_push_parser.c +111 -64
- data/ext/nokogiri/xml_schema.c +132 -140
- data/ext/nokogiri/xml_syntax_error.c +52 -23
- data/ext/nokogiri/xml_text.c +37 -30
- data/ext/nokogiri/xml_xpath_context.c +373 -185
- data/ext/nokogiri/xslt_stylesheet.c +342 -191
- data/gumbo-parser/CHANGES.md +63 -0
- data/gumbo-parser/Makefile +129 -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 +658 -0
- data/gumbo-parser/src/error.h +152 -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 +953 -0
- data/gumbo-parser/src/parser.c +4932 -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 +14 -8
- data/lib/nokogiri/css/parser.rb +399 -377
- data/lib/nokogiri/css/parser.y +250 -245
- data/lib/nokogiri/css/parser_extras.rb +16 -71
- data/lib/nokogiri/css/selector_cache.rb +38 -0
- data/lib/nokogiri/css/syntax_error.rb +3 -1
- data/lib/nokogiri/css/tokenizer.rb +7 -5
- data/lib/nokogiri/css/tokenizer.rex +11 -9
- data/lib/nokogiri/css/xpath_visitor.rb +242 -96
- data/lib/nokogiri/css.rb +122 -17
- data/lib/nokogiri/decorators/slop.rb +11 -11
- 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 +235 -0
- data/lib/nokogiri/html4/document_fragment.rb +166 -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/html4/sax/parser.rb +48 -0
- data/lib/nokogiri/html4/sax/parser_context.rb +15 -0
- data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
- data/lib/nokogiri/html4.rb +42 -0
- data/lib/nokogiri/html5/builder.rb +40 -0
- data/lib/nokogiri/html5/document.rb +199 -0
- data/lib/nokogiri/html5/document_fragment.rb +200 -0
- data/lib/nokogiri/html5/node.rb +103 -0
- data/lib/nokogiri/html5.rb +368 -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 +83 -35
- data/lib/nokogiri/xml/cdata.rb +3 -1
- data/lib/nokogiri/xml/character_data.rb +2 -0
- data/lib/nokogiri/xml/document.rb +359 -130
- data/lib/nokogiri/xml/document_fragment.rb +170 -54
- 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 +1168 -420
- data/lib/nokogiri/xml/node_set.rb +145 -67
- 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 +47 -30
- data/lib/nokogiri/xml/pp.rb +4 -2
- data/lib/nokogiri/xml/processing_instruction.rb +4 -1
- data/lib/nokogiri/xml/reader.rb +68 -41
- data/lib/nokogiri/xml/relax_ng.rb +60 -17
- data/lib/nokogiri/xml/sax/document.rb +198 -111
- data/lib/nokogiri/xml/sax/parser.rb +144 -67
- data/lib/nokogiri/xml/sax/parser_context.rb +119 -6
- data/lib/nokogiri/xml/sax/push_parser.rb +9 -5
- data/lib/nokogiri/xml/sax.rb +54 -4
- data/lib/nokogiri/xml/schema.rb +116 -39
- data/lib/nokogiri/xml/searchable.rb +139 -95
- data/lib/nokogiri/xml/syntax_error.rb +29 -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 +15 -4
- data/lib/nokogiri/xml.rb +45 -55
- data/lib/nokogiri/xslt/stylesheet.rb +32 -8
- data/lib/nokogiri/xslt.rb +103 -30
- data/lib/nokogiri.rb +59 -75
- data/lib/xsd/xmlparser/nokogiri.rb +32 -29
- 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/libxml2/0019-xpath-Use-separate-static-hash-table-for-standard-fu.patch +244 -0
- data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
- data/ports/archives/libxml2-2.13.6.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.42.tar.xz +0 -0
- metadata +123 -295
- 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.rb +0 -62
- 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/patches/libxml2/0004-libxml2.la-is-in-top_builddir.patch +0 -25
- data/patches/libxml2/0005-Fix-infinite-loop-in-xmlStringLenDecodeEntities.patch +0 -32
- 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,486 @@
|
|
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
|
+
_noko_xml_xpath_context_dfree(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 _noko_xml_xpath_context_type = {
|
22
|
+
.wrap_struct_name = "xmlXPathContext",
|
23
|
+
.function = {
|
24
|
+
.dfree = _noko_xml_xpath_context_dfree,
|
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
|
+
_noko_xml_xpath_context__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 _noko_xml_xpath_context__css_class() */
|
66
|
+
static void
|
67
|
+
noko_xml_xpath_context_xpath_func_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 (_noko_xml_xpath_context__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
|
+
noko_xml_xpath_context_xpath_func_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
|
+
* Passing a uri of +nil+ will unregister the namespace.
|
128
|
+
*
|
129
|
+
* [Returns] +self+
|
17
130
|
*/
|
18
|
-
static VALUE
|
131
|
+
static VALUE
|
132
|
+
noko_xml_xpath_context_register_ns(VALUE rb_context, VALUE prefix, VALUE uri)
|
19
133
|
{
|
20
|
-
xmlXPathContextPtr
|
21
|
-
|
134
|
+
xmlXPathContextPtr c_context;
|
135
|
+
const xmlChar *ns_uri;
|
22
136
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
137
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
138
|
+
|
139
|
+
if (NIL_P(uri)) {
|
140
|
+
ns_uri = NULL;
|
141
|
+
} else {
|
142
|
+
ns_uri = (const xmlChar *)StringValueCStr(uri);
|
143
|
+
}
|
144
|
+
|
145
|
+
xmlXPathRegisterNs(c_context, (const xmlChar *)StringValueCStr(prefix), ns_uri);
|
146
|
+
|
147
|
+
return rb_context;
|
28
148
|
}
|
29
149
|
|
30
150
|
/*
|
31
151
|
* call-seq:
|
32
|
-
*
|
152
|
+
* register_variable(name, value) → Nokogiri::XML::XPathContext
|
153
|
+
*
|
154
|
+
* Register the variable +name+ with +value+ for use in future queries.
|
155
|
+
* Passing a value of +nil+ will unregister the variable.
|
33
156
|
*
|
34
|
-
*
|
157
|
+
* [Returns] +self+
|
35
158
|
*/
|
36
|
-
static VALUE
|
159
|
+
static VALUE
|
160
|
+
noko_xml_xpath_context_register_variable(VALUE rb_context, VALUE name, VALUE value)
|
37
161
|
{
|
38
|
-
|
39
|
-
|
40
|
-
Data_Get_Struct(self, xmlXPathContext, ctx);
|
162
|
+
xmlXPathContextPtr c_context;
|
163
|
+
xmlXPathObjectPtr xmlValue;
|
41
164
|
|
42
|
-
|
165
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
43
166
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
167
|
+
if (NIL_P(value)) {
|
168
|
+
xmlValue = NULL;
|
169
|
+
} else {
|
170
|
+
xmlValue = xmlXPathNewCString(StringValueCStr(value));
|
171
|
+
}
|
172
|
+
|
173
|
+
xmlXPathRegisterVariable(c_context, (const xmlChar *)StringValueCStr(name), xmlValue);
|
48
174
|
|
49
|
-
|
175
|
+
return rb_context;
|
50
176
|
}
|
51
177
|
|
52
|
-
|
178
|
+
|
179
|
+
/*
|
180
|
+
* convert an XPath object into a Ruby object of the appropriate type.
|
181
|
+
* returns Qundef if no conversion was possible.
|
182
|
+
*/
|
183
|
+
static VALUE
|
184
|
+
_noko_xml_xpath_context__xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr c_context)
|
53
185
|
{
|
54
|
-
|
55
|
-
|
186
|
+
VALUE rb_retval;
|
187
|
+
|
188
|
+
assert(c_context->doc);
|
189
|
+
assert(DOC_RUBY_OBJECT_TEST(c_context->doc));
|
190
|
+
|
191
|
+
switch (c_xpath_object->type) {
|
192
|
+
case XPATH_STRING:
|
193
|
+
rb_retval = NOKOGIRI_STR_NEW2(c_xpath_object->stringval);
|
194
|
+
xmlFree(c_xpath_object->stringval);
|
195
|
+
return rb_retval;
|
196
|
+
|
197
|
+
case XPATH_NODESET:
|
198
|
+
return noko_xml_node_set_wrap(
|
199
|
+
c_xpath_object->nodesetval,
|
200
|
+
DOC_RUBY_OBJECT(c_context->doc)
|
201
|
+
);
|
202
|
+
|
203
|
+
case XPATH_NUMBER:
|
204
|
+
return rb_float_new(c_xpath_object->floatval);
|
205
|
+
|
206
|
+
case XPATH_BOOLEAN:
|
207
|
+
return (c_xpath_object->boolval == 1) ? Qtrue : Qfalse;
|
208
|
+
|
209
|
+
default:
|
210
|
+
return Qundef;
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
void
|
215
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(
|
216
|
+
xmlXPathParserContextPtr ctxt,
|
217
|
+
int argc,
|
218
|
+
VALUE rb_xpath_handler,
|
219
|
+
const char *method_name
|
220
|
+
)
|
221
|
+
{
|
222
|
+
VALUE rb_retval;
|
56
223
|
VALUE *argv;
|
57
|
-
VALUE
|
58
|
-
xmlNodeSetPtr
|
59
|
-
xmlXPathObjectPtr
|
224
|
+
VALUE rb_node_set = Qnil;
|
225
|
+
xmlNodeSetPtr c_node_set = NULL;
|
226
|
+
xmlXPathObjectPtr c_xpath_object;
|
60
227
|
|
61
|
-
assert(
|
62
|
-
assert(DOC_RUBY_OBJECT_TEST(
|
228
|
+
assert(ctxt->context->doc);
|
229
|
+
assert(DOC_RUBY_OBJECT_TEST(ctxt->context->doc));
|
63
230
|
|
64
|
-
argv = (VALUE *)
|
65
|
-
for (
|
66
|
-
rb_gc_register_address(&argv[
|
231
|
+
argv = (VALUE *)ruby_xcalloc((size_t)argc, sizeof(VALUE));
|
232
|
+
for (int j = 0 ; j < argc ; ++j) {
|
233
|
+
rb_gc_register_address(&argv[j]);
|
67
234
|
}
|
68
235
|
|
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);
|
236
|
+
for (int j = argc - 1 ; j >= 0 ; --j) {
|
237
|
+
c_xpath_object = valuePop(ctxt);
|
238
|
+
argv[j] = _noko_xml_xpath_context__xpath2ruby(c_xpath_object, ctxt->context);
|
239
|
+
if (argv[j] == Qundef) {
|
240
|
+
argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(c_xpath_object));
|
241
|
+
}
|
242
|
+
xmlXPathFreeNodeSetList(c_xpath_object);
|
93
243
|
}
|
94
244
|
|
95
|
-
|
245
|
+
rb_retval = rb_funcall2(
|
246
|
+
rb_xpath_handler,
|
247
|
+
rb_intern((const char *)method_name),
|
248
|
+
argc,
|
249
|
+
argv
|
250
|
+
);
|
96
251
|
|
97
|
-
for (
|
98
|
-
rb_gc_unregister_address(&argv[
|
252
|
+
for (int j = 0 ; j < argc ; ++j) {
|
253
|
+
rb_gc_unregister_address(&argv[j]);
|
99
254
|
}
|
100
|
-
|
255
|
+
ruby_xfree(argv);
|
101
256
|
|
102
|
-
switch(TYPE(
|
257
|
+
switch (TYPE(rb_retval)) {
|
103
258
|
case T_FLOAT:
|
104
259
|
case T_BIGNUM:
|
105
260
|
case T_FIXNUM:
|
106
|
-
xmlXPathReturnNumber(
|
261
|
+
xmlXPathReturnNumber(ctxt, NUM2DBL(rb_retval));
|
107
262
|
break;
|
108
263
|
case T_STRING:
|
109
|
-
xmlXPathReturnString(
|
110
|
-
ctx,
|
111
|
-
xmlCharStrdup(StringValueCStr(result))
|
112
|
-
);
|
264
|
+
xmlXPathReturnString(ctxt, xmlCharStrdup(StringValueCStr(rb_retval)));
|
113
265
|
break;
|
114
266
|
case T_TRUE:
|
115
|
-
xmlXPathReturnTrue(
|
267
|
+
xmlXPathReturnTrue(ctxt);
|
116
268
|
break;
|
117
269
|
case T_FALSE:
|
118
|
-
xmlXPathReturnFalse(
|
270
|
+
xmlXPathReturnFalse(ctxt);
|
119
271
|
break;
|
120
272
|
case T_NIL:
|
121
273
|
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
|
-
}
|
274
|
+
case T_ARRAY: {
|
275
|
+
VALUE construct_args[2] = { DOC_RUBY_OBJECT(ctxt->context->doc), rb_retval };
|
276
|
+
rb_node_set = rb_class_new_instance(2, construct_args, cNokogiriXmlNodeSet);
|
277
|
+
c_node_set = noko_xml_node_set_unwrap(rb_node_set);
|
278
|
+
xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
|
279
|
+
}
|
131
280
|
break;
|
132
281
|
case T_DATA:
|
133
|
-
if(rb_obj_is_kind_of(
|
134
|
-
|
282
|
+
if (rb_obj_is_kind_of(rb_retval, cNokogiriXmlNodeSet)) {
|
283
|
+
c_node_set = noko_xml_node_set_unwrap(rb_retval);
|
135
284
|
/* Copy the node set, otherwise it will get GC'd. */
|
136
|
-
xmlXPathReturnNodeSet(
|
285
|
+
xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
|
137
286
|
break;
|
138
287
|
}
|
139
288
|
default:
|
140
289
|
rb_raise(rb_eRuntimeError, "Invalid return type");
|
141
|
-
|
290
|
+
}
|
142
291
|
}
|
143
292
|
|
144
|
-
static void
|
293
|
+
static void
|
294
|
+
_noko_xml_xpath_context__handler_invoker(xmlXPathParserContextPtr ctxt, int argc)
|
145
295
|
{
|
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(
|
296
|
+
VALUE rb_xpath_handler = Qnil;
|
297
|
+
const char *method_name = NULL ;
|
298
|
+
|
299
|
+
assert(ctxt);
|
300
|
+
assert(ctxt->context);
|
301
|
+
assert(ctxt->context->userData);
|
302
|
+
assert(ctxt->context->function);
|
303
|
+
|
304
|
+
rb_xpath_handler = (VALUE)(ctxt->context->userData);
|
305
|
+
method_name = (const char *)(ctxt->context->function);
|
306
|
+
|
307
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(
|
308
|
+
ctxt,
|
309
|
+
argc,
|
310
|
+
rb_xpath_handler,
|
311
|
+
method_name
|
312
|
+
);
|
158
313
|
}
|
159
314
|
|
160
|
-
static xmlXPathFunction
|
161
|
-
|
162
|
-
const xmlChar* ns_uri )
|
315
|
+
static xmlXPathFunction
|
316
|
+
_noko_xml_xpath_context_handler_lookup(void *data, const xmlChar *c_name, const xmlChar *c_ns_uri)
|
163
317
|
{
|
164
|
-
VALUE
|
165
|
-
if(rb_respond_to(
|
166
|
-
|
318
|
+
VALUE rb_handler = (VALUE)data;
|
319
|
+
if (rb_respond_to(rb_handler, rb_intern((const char *)c_name))) {
|
320
|
+
if (c_ns_uri == NULL) {
|
321
|
+
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.",
|
322
|
+
c_name, c_name); // TODO deprecated in v1.15.0, remove in v1.19.0
|
323
|
+
}
|
324
|
+
return _noko_xml_xpath_context__handler_invoker;
|
325
|
+
}
|
167
326
|
|
168
327
|
return NULL;
|
169
328
|
}
|
170
329
|
|
171
|
-
|
172
|
-
static void
|
330
|
+
PRINTFLIKE_DECL(2, 3)
|
331
|
+
static void
|
332
|
+
_noko_xml_xpath_context__generic_exception_pusher(void *data, const char *msg, ...)
|
173
333
|
{
|
174
|
-
|
334
|
+
VALUE rb_errors = (VALUE)data;
|
335
|
+
VALUE rb_message;
|
336
|
+
VALUE rb_exception;
|
175
337
|
|
338
|
+
Check_Type(rb_errors, T_ARRAY);
|
339
|
+
|
340
|
+
#ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
|
341
|
+
/* It is not currently possible to pass var args from native
|
342
|
+
functions to sulong, so we work around the issue here. */
|
343
|
+
rb_message = rb_sprintf("_noko_xml_xpath_context__generic_exception_pusher: %s", msg);
|
344
|
+
#else
|
176
345
|
va_list args;
|
177
346
|
va_start(args, msg);
|
178
|
-
|
347
|
+
rb_message = rb_vsprintf(msg, args);
|
179
348
|
va_end(args);
|
349
|
+
#endif
|
180
350
|
|
181
|
-
|
351
|
+
rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
|
352
|
+
rb_ary_push(rb_errors, rb_exception);
|
182
353
|
}
|
183
354
|
|
184
355
|
/*
|
185
356
|
* call-seq:
|
186
|
-
*
|
357
|
+
* evaluate(search_path, handler = nil) → Object
|
358
|
+
*
|
359
|
+
* Evaluate the +search_path+ query.
|
187
360
|
*
|
188
|
-
*
|
361
|
+
* [Returns] an object of the appropriate type for the query, which could be +NodeSet+, a +String+,
|
362
|
+
* a +Float+, or a boolean.
|
189
363
|
*/
|
190
|
-
static VALUE
|
364
|
+
static VALUE
|
365
|
+
noko_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
|
191
366
|
{
|
192
|
-
|
193
|
-
VALUE
|
194
|
-
|
195
|
-
|
196
|
-
|
367
|
+
xmlXPathContextPtr c_context;
|
368
|
+
VALUE rb_expression = Qnil;
|
369
|
+
VALUE rb_function_lookup_handler = Qnil;
|
370
|
+
xmlChar *c_expression_str = NULL;
|
371
|
+
VALUE rb_errors = rb_ary_new();
|
372
|
+
xmlXPathObjectPtr c_xpath_object;
|
373
|
+
VALUE rb_xpath_object = Qnil;
|
197
374
|
|
198
|
-
|
375
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
199
376
|
|
200
|
-
|
201
|
-
xpath_handler = Qnil;
|
377
|
+
rb_scan_args(argc, argv, "11", &rb_expression, &rb_function_lookup_handler);
|
202
378
|
|
203
|
-
|
379
|
+
c_expression_str = (xmlChar *)StringValueCStr(rb_expression);
|
204
380
|
|
205
|
-
if(Qnil !=
|
381
|
+
if (Qnil != rb_function_lookup_handler) {
|
206
382
|
/* FIXME: not sure if this is the correct place to shove private data. */
|
207
|
-
|
208
|
-
xmlXPathRegisterFuncLookup(
|
383
|
+
c_context->userData = (void *)rb_function_lookup_handler;
|
384
|
+
xmlXPathRegisterFuncLookup(
|
385
|
+
c_context,
|
386
|
+
_noko_xml_xpath_context_handler_lookup,
|
387
|
+
(void *)rb_function_lookup_handler
|
388
|
+
);
|
209
389
|
}
|
210
390
|
|
211
|
-
|
212
|
-
xmlSetStructuredErrorFunc(
|
391
|
+
/* TODO: use xmlXPathSetErrorHandler (as of 2.13.0) */
|
392
|
+
xmlSetStructuredErrorFunc((void *)rb_errors, noko__error_array_pusher);
|
393
|
+
xmlSetGenericErrorFunc((void *)rb_errors, _noko_xml_xpath_context__generic_exception_pusher);
|
213
394
|
|
214
|
-
|
215
|
-
/* when there is a non existent function. */
|
216
|
-
xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
|
395
|
+
c_xpath_object = xmlXPathEvalExpression(c_expression_str, c_context);
|
217
396
|
|
218
|
-
xpath = xmlXPathEvalExpression(query, ctx);
|
219
397
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
220
398
|
xmlSetGenericErrorFunc(NULL, NULL);
|
221
399
|
|
222
|
-
|
223
|
-
xmlErrorPtr error = xmlGetLastError();
|
224
|
-
rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
|
225
|
-
}
|
400
|
+
xmlXPathRegisterFuncLookup(c_context, NULL, NULL);
|
226
401
|
|
227
|
-
|
228
|
-
|
402
|
+
if (c_xpath_object == NULL) {
|
403
|
+
rb_exc_raise(rb_ary_entry(rb_errors, 0));
|
404
|
+
}
|
229
405
|
|
230
|
-
|
231
|
-
|
232
|
-
|
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));
|
406
|
+
rb_xpath_object = _noko_xml_xpath_context__xpath2ruby(c_xpath_object, c_context);
|
407
|
+
if (rb_xpath_object == Qundef) {
|
408
|
+
rb_xpath_object = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
|
247
409
|
}
|
248
410
|
|
249
|
-
xmlXPathFreeNodeSetList(
|
411
|
+
xmlXPathFreeNodeSetList(c_xpath_object);
|
250
412
|
|
251
|
-
return
|
413
|
+
return rb_xpath_object;
|
252
414
|
}
|
253
415
|
|
254
416
|
/*
|
255
417
|
* call-seq:
|
256
|
-
*
|
418
|
+
* new(node)
|
257
419
|
*
|
258
|
-
* Create a new XPathContext with +node+ as the
|
420
|
+
* Create a new XPathContext with +node+ as the context node.
|
259
421
|
*/
|
260
|
-
static VALUE
|
422
|
+
static VALUE
|
423
|
+
noko_xml_xpath_context_new(VALUE klass, VALUE rb_node)
|
261
424
|
{
|
262
|
-
xmlNodePtr
|
263
|
-
xmlXPathContextPtr
|
264
|
-
VALUE
|
425
|
+
xmlNodePtr c_node;
|
426
|
+
xmlXPathContextPtr c_context;
|
427
|
+
VALUE rb_context;
|
265
428
|
|
266
|
-
|
429
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
267
430
|
|
268
|
-
|
431
|
+
#if LIBXML_VERSION < 21000
|
432
|
+
xmlXPathInit(); /* deprecated in 40483d0 */
|
433
|
+
#endif
|
269
434
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
435
|
+
c_context = xmlXPathNewContext(c_node->doc);
|
436
|
+
c_context->node = c_node;
|
437
|
+
|
438
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
439
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
|
440
|
+
|
441
|
+
xmlXPathRegisterFuncNS(c_context,
|
442
|
+
(const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
|
443
|
+
noko_xml_xpath_context_xpath_func_css_class);
|
444
|
+
xmlXPathRegisterFuncNS(c_context,
|
445
|
+
(const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
|
446
|
+
noko_xml_xpath_context_xpath_func_local_name_is);
|
447
|
+
|
448
|
+
rb_context = TypedData_Wrap_Struct(klass, &_noko_xml_xpath_context_type, c_context);
|
449
|
+
|
450
|
+
return rb_context;
|
275
451
|
}
|
276
452
|
|
277
|
-
|
278
|
-
|
453
|
+
|
454
|
+
/* :nodoc: */
|
455
|
+
static VALUE
|
456
|
+
noko_xml_xpath_context_set_node(VALUE rb_context, VALUE rb_node)
|
279
457
|
{
|
280
|
-
|
458
|
+
xmlNodePtr c_node;
|
459
|
+
xmlXPathContextPtr c_context;
|
281
460
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
461
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
462
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
463
|
+
|
464
|
+
c_context->doc = c_node->doc;
|
465
|
+
c_context->node = c_node;
|
466
|
+
|
467
|
+
return rb_node;
|
468
|
+
}
|
286
469
|
|
470
|
+
void
|
471
|
+
noko_init_xml_xpath_context(void)
|
472
|
+
{
|
287
473
|
/*
|
288
|
-
* XPathContext is the entry point for searching a Document by using XPath.
|
474
|
+
* XPathContext is the entry point for searching a +Document+ by using XPath.
|
289
475
|
*/
|
290
|
-
|
476
|
+
cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
|
477
|
+
|
478
|
+
rb_undef_alloc_func(cNokogiriXmlXpathContext);
|
291
479
|
|
292
|
-
cNokogiriXmlXpathContext
|
480
|
+
rb_define_singleton_method(cNokogiriXmlXpathContext, "new", noko_xml_xpath_context_new, 1);
|
293
481
|
|
294
|
-
|
295
|
-
rb_define_method(
|
296
|
-
rb_define_method(
|
297
|
-
rb_define_method(
|
482
|
+
rb_define_method(cNokogiriXmlXpathContext, "evaluate", noko_xml_xpath_context_evaluate, -1);
|
483
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_variable", noko_xml_xpath_context_register_variable, 2);
|
484
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_ns", noko_xml_xpath_context_register_ns, 2);
|
485
|
+
rb_define_method(cNokogiriXmlXpathContext, "node=", noko_xml_xpath_context_set_node, 1);
|
298
486
|
}
|