nokogiri 1.18.0.rc1-x86_64-linux-musl
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 +7 -0
- data/Gemfile +38 -0
- data/LICENSE-DEPENDENCIES.md +2224 -0
- data/LICENSE.md +9 -0
- data/README.md +293 -0
- data/bin/nokogiri +131 -0
- data/dependencies.yml +42 -0
- data/ext/nokogiri/depend +38 -0
- data/ext/nokogiri/extconf.rb +1173 -0
- 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/include/libexslt/exslt.h +108 -0
- data/ext/nokogiri/include/libexslt/exsltconfig.h +70 -0
- data/ext/nokogiri/include/libexslt/exsltexports.h +63 -0
- data/ext/nokogiri/include/libxml2/libxml/HTMLparser.h +336 -0
- data/ext/nokogiri/include/libxml2/libxml/HTMLtree.h +147 -0
- data/ext/nokogiri/include/libxml2/libxml/SAX.h +202 -0
- data/ext/nokogiri/include/libxml2/libxml/SAX2.h +171 -0
- data/ext/nokogiri/include/libxml2/libxml/c14n.h +115 -0
- data/ext/nokogiri/include/libxml2/libxml/catalog.h +182 -0
- data/ext/nokogiri/include/libxml2/libxml/chvalid.h +230 -0
- data/ext/nokogiri/include/libxml2/libxml/debugXML.h +217 -0
- data/ext/nokogiri/include/libxml2/libxml/dict.h +82 -0
- data/ext/nokogiri/include/libxml2/libxml/encoding.h +244 -0
- data/ext/nokogiri/include/libxml2/libxml/entities.h +166 -0
- data/ext/nokogiri/include/libxml2/libxml/globals.h +41 -0
- data/ext/nokogiri/include/libxml2/libxml/hash.h +251 -0
- data/ext/nokogiri/include/libxml2/libxml/list.h +137 -0
- data/ext/nokogiri/include/libxml2/libxml/nanoftp.h +186 -0
- data/ext/nokogiri/include/libxml2/libxml/nanohttp.h +98 -0
- data/ext/nokogiri/include/libxml2/libxml/parser.h +1390 -0
- data/ext/nokogiri/include/libxml2/libxml/parserInternals.h +671 -0
- data/ext/nokogiri/include/libxml2/libxml/pattern.h +106 -0
- data/ext/nokogiri/include/libxml2/libxml/relaxng.h +219 -0
- data/ext/nokogiri/include/libxml2/libxml/schemasInternals.h +959 -0
- data/ext/nokogiri/include/libxml2/libxml/schematron.h +143 -0
- data/ext/nokogiri/include/libxml2/libxml/threads.h +87 -0
- data/ext/nokogiri/include/libxml2/libxml/tree.h +1382 -0
- data/ext/nokogiri/include/libxml2/libxml/uri.h +106 -0
- data/ext/nokogiri/include/libxml2/libxml/valid.h +477 -0
- data/ext/nokogiri/include/libxml2/libxml/xinclude.h +136 -0
- data/ext/nokogiri/include/libxml2/libxml/xlink.h +189 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlIO.h +438 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlautomata.h +146 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlerror.h +962 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlexports.h +146 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlmemory.h +188 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlmodule.h +57 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlreader.h +436 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlregexp.h +215 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlsave.h +102 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlschemas.h +249 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlschemastypes.h +152 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlstring.h +140 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlunicode.h +366 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlversion.h +347 -0
- data/ext/nokogiri/include/libxml2/libxml/xmlwriter.h +489 -0
- data/ext/nokogiri/include/libxml2/libxml/xpath.h +579 -0
- data/ext/nokogiri/include/libxml2/libxml/xpathInternals.h +633 -0
- data/ext/nokogiri/include/libxml2/libxml/xpointer.h +138 -0
- data/ext/nokogiri/include/libxslt/attributes.h +39 -0
- data/ext/nokogiri/include/libxslt/documents.h +93 -0
- data/ext/nokogiri/include/libxslt/extensions.h +262 -0
- data/ext/nokogiri/include/libxslt/extra.h +72 -0
- data/ext/nokogiri/include/libxslt/functions.h +78 -0
- data/ext/nokogiri/include/libxslt/imports.h +75 -0
- data/ext/nokogiri/include/libxslt/keys.h +53 -0
- data/ext/nokogiri/include/libxslt/namespaces.h +68 -0
- data/ext/nokogiri/include/libxslt/numbersInternals.h +73 -0
- data/ext/nokogiri/include/libxslt/pattern.h +84 -0
- data/ext/nokogiri/include/libxslt/preproc.h +43 -0
- data/ext/nokogiri/include/libxslt/security.h +104 -0
- data/ext/nokogiri/include/libxslt/templates.h +77 -0
- data/ext/nokogiri/include/libxslt/transform.h +207 -0
- data/ext/nokogiri/include/libxslt/variables.h +118 -0
- data/ext/nokogiri/include/libxslt/xslt.h +110 -0
- data/ext/nokogiri/include/libxslt/xsltInternals.h +1995 -0
- data/ext/nokogiri/include/libxslt/xsltconfig.h +146 -0
- data/ext/nokogiri/include/libxslt/xsltexports.h +64 -0
- data/ext/nokogiri/include/libxslt/xsltlocale.h +44 -0
- data/ext/nokogiri/include/libxslt/xsltutils.h +343 -0
- data/ext/nokogiri/libxml2_polyfill.c +114 -0
- data/ext/nokogiri/nokogiri.c +294 -0
- data/ext/nokogiri/nokogiri.h +238 -0
- data/ext/nokogiri/test_global_handlers.c +40 -0
- data/ext/nokogiri/xml_attr.c +103 -0
- data/ext/nokogiri/xml_attribute_decl.c +70 -0
- data/ext/nokogiri/xml_cdata.c +62 -0
- data/ext/nokogiri/xml_comment.c +57 -0
- data/ext/nokogiri/xml_document.c +784 -0
- data/ext/nokogiri/xml_document_fragment.c +29 -0
- data/ext/nokogiri/xml_dtd.c +208 -0
- data/ext/nokogiri/xml_element_content.c +131 -0
- data/ext/nokogiri/xml_element_decl.c +69 -0
- data/ext/nokogiri/xml_encoding_handler.c +112 -0
- data/ext/nokogiri/xml_entity_decl.c +112 -0
- data/ext/nokogiri/xml_entity_reference.c +50 -0
- data/ext/nokogiri/xml_namespace.c +181 -0
- data/ext/nokogiri/xml_node.c +2459 -0
- data/ext/nokogiri/xml_node_set.c +518 -0
- data/ext/nokogiri/xml_processing_instruction.c +54 -0
- data/ext/nokogiri/xml_reader.c +777 -0
- data/ext/nokogiri/xml_relax_ng.c +149 -0
- data/ext/nokogiri/xml_sax_parser.c +403 -0
- data/ext/nokogiri/xml_sax_parser_context.c +390 -0
- data/ext/nokogiri/xml_sax_push_parser.c +206 -0
- data/ext/nokogiri/xml_schema.c +226 -0
- data/ext/nokogiri/xml_syntax_error.c +93 -0
- data/ext/nokogiri/xml_text.c +59 -0
- data/ext/nokogiri/xml_xpath_context.c +502 -0
- data/ext/nokogiri/xslt_stylesheet.c +421 -0
- data/gumbo-parser/CHANGES.md +63 -0
- data/gumbo-parser/Makefile +129 -0
- data/gumbo-parser/THANKS +27 -0
- data/lib/nokogiri/3.1/nokogiri.so +0 -0
- data/lib/nokogiri/3.2/nokogiri.so +0 -0
- data/lib/nokogiri/3.3/nokogiri.so +0 -0
- data/lib/nokogiri/3.4/nokogiri.so +0 -0
- data/lib/nokogiri/class_resolver.rb +67 -0
- data/lib/nokogiri/css/node.rb +58 -0
- data/lib/nokogiri/css/parser.rb +772 -0
- data/lib/nokogiri/css/parser.y +277 -0
- data/lib/nokogiri/css/parser_extras.rb +36 -0
- data/lib/nokogiri/css/selector_cache.rb +38 -0
- data/lib/nokogiri/css/syntax_error.rb +9 -0
- data/lib/nokogiri/css/tokenizer.rb +155 -0
- data/lib/nokogiri/css/tokenizer.rex +57 -0
- data/lib/nokogiri/css/xpath_visitor.rb +375 -0
- data/lib/nokogiri/css.rb +132 -0
- data/lib/nokogiri/decorators/slop.rb +42 -0
- 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 +48 -0
- data/lib/nokogiri/html4/builder.rb +37 -0
- data/lib/nokogiri/html4/document.rb +235 -0
- data/lib/nokogiri/html4/document_fragment.rb +166 -0
- data/lib/nokogiri/html4/element_description.rb +25 -0
- data/lib/nokogiri/html4/element_description_defaults.rb +2040 -0
- data/lib/nokogiri/html4/encoding_reader.rb +121 -0
- data/lib/nokogiri/html4/entity_lookup.rb +15 -0
- data/lib/nokogiri/html4/sax/parser.rb +48 -0
- data/lib/nokogiri/html4/sax/parser_context.rb +15 -0
- data/lib/nokogiri/html4/sax/push_parser.rb +37 -0
- 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 +6 -0
- data/lib/nokogiri/version/constant.rb +6 -0
- data/lib/nokogiri/version/info.rb +224 -0
- data/lib/nokogiri/version.rb +4 -0
- data/lib/nokogiri/xml/attr.rb +66 -0
- data/lib/nokogiri/xml/attribute_decl.rb +22 -0
- data/lib/nokogiri/xml/builder.rb +494 -0
- data/lib/nokogiri/xml/cdata.rb +13 -0
- data/lib/nokogiri/xml/character_data.rb +9 -0
- data/lib/nokogiri/xml/document.rb +514 -0
- data/lib/nokogiri/xml/document_fragment.rb +276 -0
- data/lib/nokogiri/xml/dtd.rb +34 -0
- data/lib/nokogiri/xml/element_content.rb +46 -0
- data/lib/nokogiri/xml/element_decl.rb +17 -0
- data/lib/nokogiri/xml/entity_decl.rb +23 -0
- data/lib/nokogiri/xml/entity_reference.rb +20 -0
- data/lib/nokogiri/xml/namespace.rb +57 -0
- data/lib/nokogiri/xml/node/save_options.rb +76 -0
- data/lib/nokogiri/xml/node.rb +1650 -0
- data/lib/nokogiri/xml/node_set.rb +449 -0
- data/lib/nokogiri/xml/notation.rb +19 -0
- data/lib/nokogiri/xml/parse_options.rb +213 -0
- data/lib/nokogiri/xml/pp/character_data.rb +21 -0
- data/lib/nokogiri/xml/pp/node.rb +73 -0
- data/lib/nokogiri/xml/pp.rb +4 -0
- data/lib/nokogiri/xml/processing_instruction.rb +11 -0
- data/lib/nokogiri/xml/reader.rb +139 -0
- data/lib/nokogiri/xml/relax_ng.rb +75 -0
- data/lib/nokogiri/xml/sax/document.rb +258 -0
- data/lib/nokogiri/xml/sax/parser.rb +199 -0
- data/lib/nokogiri/xml/sax/parser_context.rb +129 -0
- data/lib/nokogiri/xml/sax/push_parser.rb +64 -0
- data/lib/nokogiri/xml/sax.rb +54 -0
- data/lib/nokogiri/xml/schema.rb +140 -0
- data/lib/nokogiri/xml/searchable.rb +297 -0
- data/lib/nokogiri/xml/syntax_error.rb +94 -0
- data/lib/nokogiri/xml/text.rb +11 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +13 -0
- data/lib/nokogiri/xml/xpath.rb +21 -0
- data/lib/nokogiri/xml/xpath_context.rb +49 -0
- data/lib/nokogiri/xml.rb +65 -0
- data/lib/nokogiri/xslt/stylesheet.rb +49 -0
- data/lib/nokogiri/xslt.rb +129 -0
- data/lib/nokogiri.rb +128 -0
- data/lib/xsd/xmlparser/nokogiri.rb +105 -0
- metadata +324 -0
@@ -0,0 +1,502 @@
|
|
1
|
+
#include <nokogiri.h>
|
2
|
+
|
3
|
+
VALUE cNokogiriXmlXpathContext;
|
4
|
+
|
5
|
+
/*
|
6
|
+
* these constants have matching declarations in
|
7
|
+
* ext/java/nokogiri/internals/NokogiriNamespaceContext.java
|
8
|
+
*/
|
9
|
+
static const xmlChar *NOKOGIRI_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";
|
13
|
+
|
14
|
+
static void
|
15
|
+
_noko_xml_xpath_context_dfree(void *data)
|
16
|
+
{
|
17
|
+
xmlXPathContextPtr c_context = data;
|
18
|
+
xmlXPathFreeContext(c_context);
|
19
|
+
}
|
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
|
+
|
122
|
+
/*
|
123
|
+
* call-seq:
|
124
|
+
* register_ns(prefix, uri) → Nokogiri::XML::XPathContext
|
125
|
+
*
|
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+
|
130
|
+
*/
|
131
|
+
static VALUE
|
132
|
+
noko_xml_xpath_context_register_ns(VALUE rb_context, VALUE prefix, VALUE uri)
|
133
|
+
{
|
134
|
+
xmlXPathContextPtr c_context;
|
135
|
+
const xmlChar *ns_uri;
|
136
|
+
|
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
|
+
VALUE registered_namespaces = rb_iv_get(rb_context, "@registered_namespaces");
|
148
|
+
if (NIL_P(uri)) {
|
149
|
+
rb_hash_delete(registered_namespaces, prefix);
|
150
|
+
} else {
|
151
|
+
rb_hash_aset(registered_namespaces, prefix, Qtrue);
|
152
|
+
}
|
153
|
+
|
154
|
+
return rb_context;
|
155
|
+
}
|
156
|
+
|
157
|
+
/*
|
158
|
+
* call-seq:
|
159
|
+
* register_variable(name, value) → Nokogiri::XML::XPathContext
|
160
|
+
*
|
161
|
+
* Register the variable +name+ with +value+ for use in future queries.
|
162
|
+
* Passing a value of +nil+ will unregister the variable.
|
163
|
+
*
|
164
|
+
* [Returns] +self+
|
165
|
+
*/
|
166
|
+
static VALUE
|
167
|
+
noko_xml_xpath_context_register_variable(VALUE rb_context, VALUE name, VALUE value)
|
168
|
+
{
|
169
|
+
xmlXPathContextPtr c_context;
|
170
|
+
xmlXPathObjectPtr xmlValue;
|
171
|
+
|
172
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
173
|
+
|
174
|
+
if (NIL_P(value)) {
|
175
|
+
xmlValue = NULL;
|
176
|
+
} else {
|
177
|
+
xmlValue = xmlXPathNewCString(StringValueCStr(value));
|
178
|
+
}
|
179
|
+
|
180
|
+
xmlXPathRegisterVariable(c_context, (const xmlChar *)StringValueCStr(name), xmlValue);
|
181
|
+
|
182
|
+
VALUE registered_variables = rb_iv_get(rb_context, "@registered_variables");
|
183
|
+
if (NIL_P(value)) {
|
184
|
+
rb_hash_delete(registered_variables, name);
|
185
|
+
} else {
|
186
|
+
rb_hash_aset(registered_variables, name, Qtrue);
|
187
|
+
}
|
188
|
+
|
189
|
+
return rb_context;
|
190
|
+
}
|
191
|
+
|
192
|
+
|
193
|
+
/*
|
194
|
+
* convert an XPath object into a Ruby object of the appropriate type.
|
195
|
+
* returns Qundef if no conversion was possible.
|
196
|
+
*/
|
197
|
+
static VALUE
|
198
|
+
_noko_xml_xpath_context__xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr c_context)
|
199
|
+
{
|
200
|
+
VALUE rb_retval;
|
201
|
+
|
202
|
+
assert(c_context->doc);
|
203
|
+
assert(DOC_RUBY_OBJECT_TEST(c_context->doc));
|
204
|
+
|
205
|
+
switch (c_xpath_object->type) {
|
206
|
+
case XPATH_STRING:
|
207
|
+
rb_retval = NOKOGIRI_STR_NEW2(c_xpath_object->stringval);
|
208
|
+
xmlFree(c_xpath_object->stringval);
|
209
|
+
return rb_retval;
|
210
|
+
|
211
|
+
case XPATH_NODESET:
|
212
|
+
return noko_xml_node_set_wrap(
|
213
|
+
c_xpath_object->nodesetval,
|
214
|
+
DOC_RUBY_OBJECT(c_context->doc)
|
215
|
+
);
|
216
|
+
|
217
|
+
case XPATH_NUMBER:
|
218
|
+
return rb_float_new(c_xpath_object->floatval);
|
219
|
+
|
220
|
+
case XPATH_BOOLEAN:
|
221
|
+
return (c_xpath_object->boolval == 1) ? Qtrue : Qfalse;
|
222
|
+
|
223
|
+
default:
|
224
|
+
return Qundef;
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
void
|
229
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(
|
230
|
+
xmlXPathParserContextPtr ctxt,
|
231
|
+
int argc,
|
232
|
+
VALUE rb_xpath_handler,
|
233
|
+
const char *method_name
|
234
|
+
)
|
235
|
+
{
|
236
|
+
VALUE rb_retval;
|
237
|
+
VALUE *argv;
|
238
|
+
VALUE rb_node_set = Qnil;
|
239
|
+
xmlNodeSetPtr c_node_set = NULL;
|
240
|
+
xmlXPathObjectPtr c_xpath_object;
|
241
|
+
|
242
|
+
assert(ctxt->context->doc);
|
243
|
+
assert(DOC_RUBY_OBJECT_TEST(ctxt->context->doc));
|
244
|
+
|
245
|
+
argv = (VALUE *)ruby_xcalloc((size_t)argc, sizeof(VALUE));
|
246
|
+
for (int j = 0 ; j < argc ; ++j) {
|
247
|
+
rb_gc_register_address(&argv[j]);
|
248
|
+
}
|
249
|
+
|
250
|
+
for (int j = argc - 1 ; j >= 0 ; --j) {
|
251
|
+
c_xpath_object = valuePop(ctxt);
|
252
|
+
argv[j] = _noko_xml_xpath_context__xpath2ruby(c_xpath_object, ctxt->context);
|
253
|
+
if (argv[j] == Qundef) {
|
254
|
+
argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(c_xpath_object));
|
255
|
+
}
|
256
|
+
xmlXPathFreeNodeSetList(c_xpath_object);
|
257
|
+
}
|
258
|
+
|
259
|
+
rb_retval = rb_funcall2(
|
260
|
+
rb_xpath_handler,
|
261
|
+
rb_intern((const char *)method_name),
|
262
|
+
argc,
|
263
|
+
argv
|
264
|
+
);
|
265
|
+
|
266
|
+
for (int j = 0 ; j < argc ; ++j) {
|
267
|
+
rb_gc_unregister_address(&argv[j]);
|
268
|
+
}
|
269
|
+
ruby_xfree(argv);
|
270
|
+
|
271
|
+
switch (TYPE(rb_retval)) {
|
272
|
+
case T_FLOAT:
|
273
|
+
case T_BIGNUM:
|
274
|
+
case T_FIXNUM:
|
275
|
+
xmlXPathReturnNumber(ctxt, NUM2DBL(rb_retval));
|
276
|
+
break;
|
277
|
+
case T_STRING:
|
278
|
+
xmlXPathReturnString(ctxt, xmlCharStrdup(StringValueCStr(rb_retval)));
|
279
|
+
break;
|
280
|
+
case T_TRUE:
|
281
|
+
xmlXPathReturnTrue(ctxt);
|
282
|
+
break;
|
283
|
+
case T_FALSE:
|
284
|
+
xmlXPathReturnFalse(ctxt);
|
285
|
+
break;
|
286
|
+
case T_NIL:
|
287
|
+
break;
|
288
|
+
case T_ARRAY: {
|
289
|
+
VALUE construct_args[2] = { DOC_RUBY_OBJECT(ctxt->context->doc), rb_retval };
|
290
|
+
rb_node_set = rb_class_new_instance(2, construct_args, cNokogiriXmlNodeSet);
|
291
|
+
c_node_set = noko_xml_node_set_unwrap(rb_node_set);
|
292
|
+
xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
|
293
|
+
}
|
294
|
+
break;
|
295
|
+
case T_DATA:
|
296
|
+
if (rb_obj_is_kind_of(rb_retval, cNokogiriXmlNodeSet)) {
|
297
|
+
c_node_set = noko_xml_node_set_unwrap(rb_retval);
|
298
|
+
/* Copy the node set, otherwise it will get GC'd. */
|
299
|
+
xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
|
300
|
+
break;
|
301
|
+
}
|
302
|
+
default:
|
303
|
+
rb_raise(rb_eRuntimeError, "Invalid return type");
|
304
|
+
}
|
305
|
+
}
|
306
|
+
|
307
|
+
static void
|
308
|
+
_noko_xml_xpath_context__handler_invoker(xmlXPathParserContextPtr ctxt, int argc)
|
309
|
+
{
|
310
|
+
VALUE rb_xpath_handler = Qnil;
|
311
|
+
const char *method_name = NULL ;
|
312
|
+
|
313
|
+
assert(ctxt);
|
314
|
+
assert(ctxt->context);
|
315
|
+
assert(ctxt->context->userData);
|
316
|
+
assert(ctxt->context->function);
|
317
|
+
|
318
|
+
rb_xpath_handler = (VALUE)(ctxt->context->userData);
|
319
|
+
method_name = (const char *)(ctxt->context->function);
|
320
|
+
|
321
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(
|
322
|
+
ctxt,
|
323
|
+
argc,
|
324
|
+
rb_xpath_handler,
|
325
|
+
method_name
|
326
|
+
);
|
327
|
+
}
|
328
|
+
|
329
|
+
static xmlXPathFunction
|
330
|
+
_noko_xml_xpath_context_handler_lookup(void *data, const xmlChar *c_name, const xmlChar *c_ns_uri)
|
331
|
+
{
|
332
|
+
VALUE rb_handler = (VALUE)data;
|
333
|
+
if (rb_respond_to(rb_handler, rb_intern((const char *)c_name))) {
|
334
|
+
if (c_ns_uri == NULL) {
|
335
|
+
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.",
|
336
|
+
c_name, c_name); // TODO deprecated in v1.15.0, remove in v1.19.0
|
337
|
+
}
|
338
|
+
return _noko_xml_xpath_context__handler_invoker;
|
339
|
+
}
|
340
|
+
|
341
|
+
return NULL;
|
342
|
+
}
|
343
|
+
|
344
|
+
PRINTFLIKE_DECL(2, 3)
|
345
|
+
static void
|
346
|
+
_noko_xml_xpath_context__generic_exception_pusher(void *data, const char *msg, ...)
|
347
|
+
{
|
348
|
+
VALUE rb_errors = (VALUE)data;
|
349
|
+
VALUE rb_message;
|
350
|
+
VALUE rb_exception;
|
351
|
+
|
352
|
+
Check_Type(rb_errors, T_ARRAY);
|
353
|
+
|
354
|
+
#ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
|
355
|
+
/* It is not currently possible to pass var args from native
|
356
|
+
functions to sulong, so we work around the issue here. */
|
357
|
+
rb_message = rb_sprintf("_noko_xml_xpath_context__generic_exception_pusher: %s", msg);
|
358
|
+
#else
|
359
|
+
va_list args;
|
360
|
+
va_start(args, msg);
|
361
|
+
rb_message = rb_vsprintf(msg, args);
|
362
|
+
va_end(args);
|
363
|
+
#endif
|
364
|
+
|
365
|
+
rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
|
366
|
+
rb_ary_push(rb_errors, rb_exception);
|
367
|
+
}
|
368
|
+
|
369
|
+
/*
|
370
|
+
* call-seq:
|
371
|
+
* evaluate(search_path, handler = nil) → Object
|
372
|
+
*
|
373
|
+
* Evaluate the +search_path+ query.
|
374
|
+
*
|
375
|
+
* [Returns] an object of the appropriate type for the query, which could be +NodeSet+, a +String+,
|
376
|
+
* a +Float+, or a boolean.
|
377
|
+
*/
|
378
|
+
static VALUE
|
379
|
+
noko_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
|
380
|
+
{
|
381
|
+
xmlXPathContextPtr c_context;
|
382
|
+
VALUE rb_expression = Qnil;
|
383
|
+
VALUE rb_function_lookup_handler = Qnil;
|
384
|
+
xmlChar *c_expression_str = NULL;
|
385
|
+
VALUE rb_errors = rb_ary_new();
|
386
|
+
xmlXPathObjectPtr c_xpath_object;
|
387
|
+
VALUE rb_xpath_object = Qnil;
|
388
|
+
|
389
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
390
|
+
|
391
|
+
rb_scan_args(argc, argv, "11", &rb_expression, &rb_function_lookup_handler);
|
392
|
+
|
393
|
+
c_expression_str = (xmlChar *)StringValueCStr(rb_expression);
|
394
|
+
|
395
|
+
if (Qnil != rb_function_lookup_handler) {
|
396
|
+
/* FIXME: not sure if this is the correct place to shove private data. */
|
397
|
+
c_context->userData = (void *)rb_function_lookup_handler;
|
398
|
+
xmlXPathRegisterFuncLookup(
|
399
|
+
c_context,
|
400
|
+
_noko_xml_xpath_context_handler_lookup,
|
401
|
+
(void *)rb_function_lookup_handler
|
402
|
+
);
|
403
|
+
}
|
404
|
+
|
405
|
+
xmlSetStructuredErrorFunc((void *)rb_errors, noko__error_array_pusher);
|
406
|
+
xmlSetGenericErrorFunc((void *)rb_errors, _noko_xml_xpath_context__generic_exception_pusher);
|
407
|
+
|
408
|
+
c_xpath_object = xmlXPathEvalExpression(c_expression_str, c_context);
|
409
|
+
|
410
|
+
xmlSetStructuredErrorFunc(NULL, NULL);
|
411
|
+
xmlSetGenericErrorFunc(NULL, NULL);
|
412
|
+
|
413
|
+
xmlXPathRegisterFuncLookup(c_context, NULL, NULL);
|
414
|
+
|
415
|
+
if (c_xpath_object == NULL) {
|
416
|
+
rb_exc_raise(rb_ary_entry(rb_errors, 0));
|
417
|
+
}
|
418
|
+
|
419
|
+
rb_xpath_object = _noko_xml_xpath_context__xpath2ruby(c_xpath_object, c_context);
|
420
|
+
if (rb_xpath_object == Qundef) {
|
421
|
+
rb_xpath_object = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
|
422
|
+
}
|
423
|
+
|
424
|
+
xmlXPathFreeNodeSetList(c_xpath_object);
|
425
|
+
|
426
|
+
return rb_xpath_object;
|
427
|
+
}
|
428
|
+
|
429
|
+
/*
|
430
|
+
* call-seq:
|
431
|
+
* new(node)
|
432
|
+
*
|
433
|
+
* Create a new XPathContext with +node+ as the context node.
|
434
|
+
*/
|
435
|
+
static VALUE
|
436
|
+
noko_xml_xpath_context_new(VALUE klass, VALUE rb_node)
|
437
|
+
{
|
438
|
+
xmlNodePtr c_node;
|
439
|
+
xmlXPathContextPtr c_context;
|
440
|
+
VALUE rb_context;
|
441
|
+
|
442
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
443
|
+
|
444
|
+
#if LIBXML_VERSION < 21000
|
445
|
+
xmlXPathInit(); /* deprecated in 40483d0 */
|
446
|
+
#endif
|
447
|
+
|
448
|
+
c_context = xmlXPathNewContext(c_node->doc);
|
449
|
+
c_context->node = c_node;
|
450
|
+
|
451
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
|
452
|
+
xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
|
453
|
+
|
454
|
+
xmlXPathRegisterFuncNS(c_context,
|
455
|
+
(const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
|
456
|
+
noko_xml_xpath_context_xpath_func_css_class);
|
457
|
+
xmlXPathRegisterFuncNS(c_context,
|
458
|
+
(const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
|
459
|
+
noko_xml_xpath_context_xpath_func_local_name_is);
|
460
|
+
|
461
|
+
rb_context = TypedData_Wrap_Struct(klass, &_noko_xml_xpath_context_type, c_context);
|
462
|
+
|
463
|
+
rb_iv_set(rb_context, "@registered_namespaces", rb_hash_new());
|
464
|
+
rb_iv_set(rb_context, "@registered_variables", rb_hash_new());
|
465
|
+
|
466
|
+
return rb_context;
|
467
|
+
}
|
468
|
+
|
469
|
+
|
470
|
+
/* :nodoc: */
|
471
|
+
static VALUE
|
472
|
+
noko_xml_xpath_context_set_node(VALUE rb_context, VALUE rb_node)
|
473
|
+
{
|
474
|
+
xmlNodePtr c_node;
|
475
|
+
xmlXPathContextPtr c_context;
|
476
|
+
|
477
|
+
TypedData_Get_Struct(rb_context, xmlXPathContext, &_noko_xml_xpath_context_type, c_context);
|
478
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
479
|
+
|
480
|
+
c_context->doc = c_node->doc;
|
481
|
+
c_context->node = c_node;
|
482
|
+
|
483
|
+
return rb_node;
|
484
|
+
}
|
485
|
+
|
486
|
+
void
|
487
|
+
noko_init_xml_xpath_context(void)
|
488
|
+
{
|
489
|
+
/*
|
490
|
+
* XPathContext is the entry point for searching a +Document+ by using XPath.
|
491
|
+
*/
|
492
|
+
cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
|
493
|
+
|
494
|
+
rb_undef_alloc_func(cNokogiriXmlXpathContext);
|
495
|
+
|
496
|
+
rb_define_singleton_method(cNokogiriXmlXpathContext, "new", noko_xml_xpath_context_new, 1);
|
497
|
+
|
498
|
+
rb_define_method(cNokogiriXmlXpathContext, "evaluate", noko_xml_xpath_context_evaluate, -1);
|
499
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_variable", noko_xml_xpath_context_register_variable, 2);
|
500
|
+
rb_define_method(cNokogiriXmlXpathContext, "register_ns", noko_xml_xpath_context_register_ns, 2);
|
501
|
+
rb_define_method(cNokogiriXmlXpathContext, "node=", noko_xml_xpath_context_set_node, 1);
|
502
|
+
}
|