nokogiri 1.9.1 → 1.15.3
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 +45 -0
- data/LICENSE-DEPENDENCIES.md +1636 -1024
- data/LICENSE.md +5 -28
- data/README.md +203 -89
- data/bin/nokogiri +63 -50
- data/dependencies.yml +33 -61
- data/ext/nokogiri/depend +38 -358
- data/ext/nokogiri/extconf.rb +864 -418
- 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 +215 -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 +40 -31
- data/ext/nokogiri/xml_comment.c +20 -27
- data/ext/nokogiri/xml_document.c +401 -240
- 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 +135 -61
- data/ext/nokogiri/xml_node.c +1346 -677
- data/ext/nokogiri/xml_node_set.c +246 -216
- data/ext/nokogiri/xml_processing_instruction.c +18 -20
- data/ext/nokogiri/xml_reader.c +347 -212
- data/ext/nokogiri/xml_relax_ng.c +86 -77
- data/ext/nokogiri/xml_sax_parser.c +149 -124
- data/ext/nokogiri/xml_sax_parser_context.c +145 -103
- data/ext/nokogiri/xml_sax_push_parser.c +64 -36
- data/ext/nokogiri/xml_schema.c +138 -81
- data/ext/nokogiri/xml_syntax_error.c +42 -21
- data/ext/nokogiri/xml_text.c +36 -26
- data/ext/nokogiri/xml_xpath_context.c +366 -178
- data/ext/nokogiri/xslt_stylesheet.c +335 -189
- data/gumbo-parser/CHANGES.md +63 -0
- data/gumbo-parser/Makefile +111 -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 +3463 -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 +107 -104
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +224 -95
- 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 +392 -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 +223 -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 +98 -54
- data/lib/nokogiri/xml/cdata.rb +3 -1
- data/lib/nokogiri/xml/character_data.rb +2 -0
- data/lib/nokogiri/xml/document.rb +312 -126
- 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 +45 -0
- data/lib/nokogiri/xml/node/save_options.rb +23 -8
- data/lib/nokogiri/xml/node.rb +1088 -418
- data/lib/nokogiri/xml/node_set.rb +173 -63
- 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 +6 -4
- 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 +38 -37
- 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/0001-Remove-script-macro-support.patch +40 -0
- data/patches/libxml2/0002-Update-entities-to-remove-handling-of-ssi.patch +44 -0
- data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +25 -0
- 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.11.4.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.38.tar.xz +0 -0
- metadata +128 -265
- 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/patches/libxml2/0002-Fix-nullptr-deref-with-XPath-logic-ops.patch +0 -54
- data/patches/libxml2/0003-Fix-infinite-loop-in-LZMA-decompression.patch +0 -50
- data/ports/archives/libxml2-2.9.8.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.32.tar.gz +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
|
+
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(
|
325
|
+
"A custom XPath or CSS handler function named '%s' is being invoked without a namespace."
|
326
|
+
" Please update your query to reference this function as 'nokogiri:%s'."
|
327
|
+
" Invoking custom handler functions without a namespace is deprecated and support will be removed in a future release of Nokogiri.",
|
328
|
+
c_name, c_name);
|
329
|
+
}
|
330
|
+
return method_caller;
|
331
|
+
}
|
167
332
|
|
168
333
|
return NULL;
|
169
334
|
}
|
170
335
|
|
171
|
-
|
172
|
-
static void
|
336
|
+
PRINTFLIKE_DECL(2, 3)
|
337
|
+
static void
|
338
|
+
generic_exception_pusher(void *data, const char *msg, ...)
|
173
339
|
{
|
174
|
-
|
340
|
+
VALUE rb_errors = (VALUE)data;
|
341
|
+
VALUE rb_message;
|
342
|
+
VALUE rb_exception;
|
343
|
+
|
344
|
+
Check_Type(rb_errors, T_ARRAY);
|
175
345
|
|
346
|
+
#ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
|
347
|
+
/* It is not currently possible to pass var args from native
|
348
|
+
functions to sulong, so we work around the issue here. */
|
349
|
+
rb_message = rb_sprintf("generic_exception_pusher: %s", msg);
|
350
|
+
#else
|
176
351
|
va_list args;
|
177
352
|
va_start(args, msg);
|
178
|
-
|
353
|
+
rb_message = rb_vsprintf(msg, args);
|
179
354
|
va_end(args);
|
355
|
+
#endif
|
180
356
|
|
181
|
-
|
357
|
+
rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
|
358
|
+
rb_ary_push(rb_errors, rb_exception);
|
182
359
|
}
|
183
360
|
|
184
361
|
/*
|
185
362
|
* call-seq:
|
186
|
-
*
|
363
|
+
* evaluate(search_path, handler = nil) → Object
|
187
364
|
*
|
188
|
-
* Evaluate the +search_path+
|
365
|
+
* Evaluate the +search_path+ query.
|
366
|
+
*
|
367
|
+
* [Returns] an object of the appropriate type for the query, which could be +NodeSet+, a +String+,
|
368
|
+
* a +Float+, or a boolean.
|
189
369
|
*/
|
190
|
-
static VALUE
|
370
|
+
static VALUE
|
371
|
+
rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
|
191
372
|
{
|
192
373
|
VALUE search_path, xpath_handler;
|
193
|
-
VALUE
|
194
|
-
xmlXPathContextPtr
|
374
|
+
VALUE retval = Qnil;
|
375
|
+
xmlXPathContextPtr c_context;
|
195
376
|
xmlXPathObjectPtr xpath;
|
196
377
|
xmlChar *query;
|
378
|
+
VALUE errors = rb_ary_new();
|
197
379
|
|
198
|
-
|
380
|
+
TypedData_Get_Struct(
|
381
|
+
rb_context,
|
382
|
+
xmlXPathContext,
|
383
|
+
&xml_xpath_context_type,
|
384
|
+
c_context
|
385
|
+
);
|
199
386
|
|
200
|
-
if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1)
|
387
|
+
if (rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) {
|
201
388
|
xpath_handler = Qnil;
|
389
|
+
}
|
202
390
|
|
203
391
|
query = (xmlChar *)StringValueCStr(search_path);
|
204
392
|
|
205
|
-
if(Qnil != xpath_handler) {
|
393
|
+
if (Qnil != xpath_handler) {
|
206
394
|
/* FIXME: not sure if this is the correct place to shove private data. */
|
207
|
-
|
208
|
-
xmlXPathRegisterFuncLookup(
|
395
|
+
c_context->userData = (void *)xpath_handler;
|
396
|
+
xmlXPathRegisterFuncLookup(
|
397
|
+
c_context,
|
398
|
+
handler_lookup,
|
399
|
+
(void *)xpath_handler
|
400
|
+
);
|
209
401
|
}
|
210
402
|
|
211
|
-
|
212
|
-
|
403
|
+
xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
|
404
|
+
xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
|
213
405
|
|
214
|
-
|
215
|
-
/* when there is a non existent function. */
|
216
|
-
xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
|
406
|
+
xpath = xmlXPathEvalExpression(query, c_context);
|
217
407
|
|
218
|
-
xpath = xmlXPathEvalExpression(query, ctx);
|
219
408
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
220
409
|
xmlSetGenericErrorFunc(NULL, NULL);
|
221
410
|
|
222
|
-
if(xpath == NULL) {
|
223
|
-
|
224
|
-
rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
|
411
|
+
if (xpath == NULL) {
|
412
|
+
rb_exc_raise(rb_ary_entry(errors, 0));
|
225
413
|
}
|
226
414
|
|
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));
|
415
|
+
retval = xpath2ruby(xpath, c_context);
|
416
|
+
if (retval == Qundef) {
|
417
|
+
retval = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
|
247
418
|
}
|
248
419
|
|
249
420
|
xmlXPathFreeNodeSetList(xpath);
|
250
421
|
|
251
|
-
return
|
422
|
+
return retval;
|
252
423
|
}
|
253
424
|
|
254
425
|
/*
|
255
426
|
* call-seq:
|
256
|
-
*
|
427
|
+
* new(node)
|
257
428
|
*
|
258
|
-
* Create a new XPathContext with +node+ as the
|
429
|
+
* Create a new XPathContext with +node+ as the context node.
|
259
430
|
*/
|
260
|
-
static VALUE
|
431
|
+
static VALUE
|
432
|
+
rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
|
261
433
|
{
|
262
434
|
xmlNodePtr node;
|
263
|
-
xmlXPathContextPtr
|
264
|
-
VALUE
|
435
|
+
xmlXPathContextPtr c_context;
|
436
|
+
VALUE rb_context;
|
265
437
|
|
266
|
-
|
438
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, node);
|
267
439
|
|
268
|
-
|
440
|
+
#if LIBXML_VERSION < 21000
|
441
|
+
/* deprecated in 40483d0 */
|
442
|
+
xmlXPathInit();
|
443
|
+
#endif
|
444
|
+
|
445
|
+
c_context = xmlXPathNewContext(node->doc);
|
446
|
+
c_context->node = node;
|
447
|
+
|
448
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
449
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
|
450
|
+
xmlXPathRegisterFuncNS(
|
451
|
+
c_context,
|
452
|
+
(const xmlChar *)"css-class",
|
453
|
+
NOKOGIRI_BUILTIN_URI,
|
454
|
+
xpath_builtin_css_class
|
455
|
+
);
|
456
|
+
xmlXPathRegisterFuncNS(
|
457
|
+
c_context,
|
458
|
+
(const xmlChar *)"local-name-is",
|
459
|
+
NOKOGIRI_BUILTIN_URI,
|
460
|
+
xpath_builtin_local_name_is
|
461
|
+
);
|
269
462
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
463
|
+
rb_context = TypedData_Wrap_Struct(
|
464
|
+
klass,
|
465
|
+
&xml_xpath_context_type,
|
466
|
+
c_context
|
467
|
+
);
|
468
|
+
return rb_context;
|
275
469
|
}
|
276
470
|
|
277
|
-
|
278
|
-
|
471
|
+
void
|
472
|
+
noko_init_xml_xpath_context(void)
|
279
473
|
{
|
280
|
-
VALUE module = rb_define_module("Nokogiri");
|
281
|
-
|
282
474
|
/*
|
283
|
-
*
|
475
|
+
* XPathContext is the entry point for searching a +Document+ by using XPath.
|
284
476
|
*/
|
285
|
-
|
477
|
+
cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
|
286
478
|
|
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);
|
479
|
+
rb_undef_alloc_func(cNokogiriXmlXpathContext);
|
291
480
|
|
292
|
-
cNokogiriXmlXpathContext
|
481
|
+
rb_define_singleton_method(cNokogiriXmlXpathContext, "new", rb_xml_xpath_context_new, 1);
|
293
482
|
|
294
|
-
|
295
|
-
rb_define_method(
|
296
|
-
rb_define_method(
|
297
|
-
rb_define_method(klass, "register_ns", register_ns, 2);
|
483
|
+
rb_define_method(cNokogiriXmlXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
|
484
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
|
485
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
|
298
486
|
}
|