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