nokogiri 1.11.1 → 1.11.2
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/LICENSE-DEPENDENCIES.md +12 -12
- data/LICENSE.md +1 -1
- data/README.md +20 -15
- data/ext/nokogiri/depend +34 -474
- data/ext/nokogiri/extconf.rb +253 -183
- data/ext/nokogiri/html_document.c +10 -15
- data/ext/nokogiri/html_element_description.c +84 -71
- data/ext/nokogiri/html_entity_lookup.c +21 -16
- data/ext/nokogiri/html_sax_parser_context.c +66 -65
- data/ext/nokogiri/html_sax_push_parser.c +29 -27
- data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
- data/ext/nokogiri/nokogiri.c +171 -63
- data/ext/nokogiri/nokogiri.h +158 -75
- data/ext/nokogiri/test_global_handlers.c +3 -4
- data/ext/nokogiri/xml_attr.c +15 -15
- data/ext/nokogiri/xml_attribute_decl.c +18 -18
- data/ext/nokogiri/xml_cdata.c +13 -18
- data/ext/nokogiri/xml_comment.c +19 -26
- data/ext/nokogiri/xml_document.c +221 -164
- data/ext/nokogiri/xml_document_fragment.c +13 -15
- data/ext/nokogiri/xml_dtd.c +54 -48
- data/ext/nokogiri/xml_element_content.c +30 -27
- data/ext/nokogiri/xml_element_decl.c +22 -22
- data/ext/nokogiri/xml_encoding_handler.c +17 -11
- data/ext/nokogiri/xml_entity_decl.c +32 -30
- data/ext/nokogiri/xml_entity_reference.c +16 -18
- data/ext/nokogiri/xml_namespace.c +56 -49
- data/ext/nokogiri/xml_node.c +338 -286
- data/ext/nokogiri/xml_node_set.c +168 -156
- data/ext/nokogiri/xml_processing_instruction.c +17 -19
- data/ext/nokogiri/xml_reader.c +191 -157
- data/ext/nokogiri/xml_relax_ng.c +29 -23
- data/ext/nokogiri/xml_sax_parser.c +117 -112
- data/ext/nokogiri/xml_sax_parser_context.c +100 -85
- data/ext/nokogiri/xml_sax_push_parser.c +34 -27
- data/ext/nokogiri/xml_schema.c +48 -42
- data/ext/nokogiri/xml_syntax_error.c +21 -23
- data/ext/nokogiri/xml_text.c +13 -17
- data/ext/nokogiri/xml_xpath_context.c +134 -127
- data/ext/nokogiri/xslt_stylesheet.c +157 -157
- data/lib/nokogiri.rb +1 -22
- data/lib/nokogiri/css/parser.rb +1 -1
- data/lib/nokogiri/extension.rb +26 -0
- data/lib/nokogiri/html/document_fragment.rb +15 -15
- data/lib/nokogiri/version/constant.rb +1 -1
- data/lib/nokogiri/version/info.rb +31 -8
- data/lib/nokogiri/xml/document.rb +31 -11
- data/lib/nokogiri/xml/node.rb +38 -42
- data/lib/nokogiri/xml/reader.rb +2 -9
- data/lib/nokogiri/xml/xpath.rb +1 -3
- data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
- data/patches/libxml2/0010-parser.c-shrink-the-input-buffer-when-appropriate.patch +70 -0
- metadata +8 -41
- data/ext/nokogiri/html_document.h +0 -10
- data/ext/nokogiri/html_element_description.h +0 -10
- data/ext/nokogiri/html_entity_lookup.h +0 -8
- data/ext/nokogiri/html_sax_parser_context.h +0 -11
- 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 -63
- 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 -25
- 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
@@ -1,31 +1,29 @@
|
|
1
|
-
#include <
|
1
|
+
#include <nokogiri.h>
|
2
2
|
|
3
|
-
|
4
|
-
#include <libxslt/xsltutils.h>
|
5
|
-
#include <libxslt/transform.h>
|
6
|
-
#include <libexslt/exslt.h>
|
7
|
-
|
8
|
-
VALUE xslt;
|
3
|
+
VALUE cNokogiriXsltStylesheet ;
|
9
4
|
|
10
|
-
static void
|
5
|
+
static void
|
6
|
+
mark(nokogiriXsltStylesheetTuple *wrapper)
|
11
7
|
{
|
12
8
|
rb_gc_mark(wrapper->func_instances);
|
13
9
|
}
|
14
10
|
|
15
|
-
static void
|
11
|
+
static void
|
12
|
+
dealloc(nokogiriXsltStylesheetTuple *wrapper)
|
16
13
|
{
|
17
|
-
|
14
|
+
xsltStylesheetPtr doc = wrapper->ss;
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
NOKOGIRI_DEBUG_START(doc);
|
17
|
+
xsltFreeStylesheet(doc); /* commented out for now. */
|
18
|
+
NOKOGIRI_DEBUG_END(doc);
|
22
19
|
|
23
|
-
|
20
|
+
free(wrapper);
|
24
21
|
}
|
25
22
|
|
26
|
-
static void
|
23
|
+
static void
|
24
|
+
xslt_generic_error_handler(void *ctx, const char *msg, ...)
|
27
25
|
{
|
28
|
-
char *
|
26
|
+
char *message;
|
29
27
|
|
30
28
|
va_list args;
|
31
29
|
va_start(args, msg);
|
@@ -37,7 +35,8 @@ static void xslt_generic_error_handler(void * ctx, const char *msg, ...)
|
|
37
35
|
free(message);
|
38
36
|
}
|
39
37
|
|
40
|
-
VALUE
|
38
|
+
VALUE
|
39
|
+
Nokogiri_wrap_xslt_stylesheet(xsltStylesheetPtr ss)
|
41
40
|
{
|
42
41
|
VALUE self;
|
43
42
|
nokogiriXsltStylesheetTuple *wrapper;
|
@@ -58,29 +57,30 @@ VALUE Nokogiri_wrap_xslt_stylesheet(xsltStylesheetPtr ss)
|
|
58
57
|
*
|
59
58
|
* Parse a stylesheet from +document+.
|
60
59
|
*/
|
61
|
-
static VALUE
|
60
|
+
static VALUE
|
61
|
+
parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
|
62
62
|
{
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
xmlDocPtr xml, xml_cpy;
|
64
|
+
VALUE errstr, exception;
|
65
|
+
xsltStylesheetPtr ss ;
|
66
|
+
Data_Get_Struct(xmldocobj, xmlDoc, xml);
|
67
|
+
exsltRegisterAll();
|
68
68
|
|
69
|
-
|
70
|
-
|
69
|
+
errstr = rb_str_new(0, 0);
|
70
|
+
xsltSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
|
71
71
|
|
72
|
-
|
73
|
-
|
72
|
+
xml_cpy = xmlCopyDoc(xml, 1); /* 1 => recursive */
|
73
|
+
ss = xsltParseStylesheetDoc(xml_cpy);
|
74
74
|
|
75
|
-
|
75
|
+
xsltSetGenericErrorFunc(NULL, NULL);
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
77
|
+
if (!ss) {
|
78
|
+
xmlFreeDoc(xml_cpy);
|
79
|
+
exception = rb_exc_new3(rb_eRuntimeError, errstr);
|
80
|
+
rb_exc_raise(exception);
|
81
|
+
}
|
82
82
|
|
83
|
-
|
83
|
+
return Nokogiri_wrap_xslt_stylesheet(ss);
|
84
84
|
}
|
85
85
|
|
86
86
|
|
@@ -90,20 +90,21 @@ static VALUE parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
|
|
90
90
|
*
|
91
91
|
* Serialize +document+ to an xml string.
|
92
92
|
*/
|
93
|
-
static VALUE
|
93
|
+
static VALUE
|
94
|
+
serialize(VALUE self, VALUE xmlobj)
|
94
95
|
{
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
96
|
+
xmlDocPtr xml ;
|
97
|
+
nokogiriXsltStylesheetTuple *wrapper;
|
98
|
+
xmlChar *doc_ptr ;
|
99
|
+
int doc_len ;
|
100
|
+
VALUE rval ;
|
101
|
+
|
102
|
+
Data_Get_Struct(xmlobj, xmlDoc, xml);
|
103
|
+
Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
|
104
|
+
xsltSaveResultToString(&doc_ptr, &doc_len, xml, wrapper->ss);
|
105
|
+
rval = NOKOGIRI_STR_NEW(doc_ptr, doc_len);
|
106
|
+
xmlFree(doc_ptr);
|
107
|
+
return rval ;
|
107
108
|
}
|
108
109
|
|
109
110
|
/*
|
@@ -121,109 +122,114 @@ static VALUE serialize(VALUE self, VALUE xmlobj)
|
|
121
122
|
* puts xslt.transform(doc, ['key', 'value'])
|
122
123
|
*
|
123
124
|
*/
|
124
|
-
static VALUE
|
125
|
+
static VALUE
|
126
|
+
transform(int argc, VALUE *argv, VALUE self)
|
125
127
|
{
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
128
|
+
VALUE xmldoc, paramobj, errstr, exception ;
|
129
|
+
xmlDocPtr xml ;
|
130
|
+
xmlDocPtr result ;
|
131
|
+
nokogiriXsltStylesheetTuple *wrapper;
|
132
|
+
const char **params ;
|
133
|
+
long param_len, j ;
|
134
|
+
int parse_error_occurred ;
|
135
|
+
|
136
|
+
rb_scan_args(argc, argv, "11", &xmldoc, ¶mobj);
|
137
|
+
if (NIL_P(paramobj)) { paramobj = rb_ary_new2(0L) ; }
|
138
|
+
if (!rb_obj_is_kind_of(xmldoc, cNokogiriXmlDocument)) {
|
139
|
+
rb_raise(rb_eArgError, "argument must be a Nokogiri::XML::Document");
|
140
|
+
}
|
141
|
+
|
142
|
+
/* handle hashes as arguments. */
|
143
|
+
if (T_HASH == TYPE(paramobj)) {
|
144
|
+
paramobj = rb_funcall(paramobj, rb_intern("to_a"), 0);
|
145
|
+
paramobj = rb_funcall(paramobj, rb_intern("flatten"), 0);
|
146
|
+
}
|
147
|
+
|
148
|
+
Check_Type(paramobj, T_ARRAY);
|
149
|
+
|
150
|
+
Data_Get_Struct(xmldoc, xmlDoc, xml);
|
151
|
+
Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
|
152
|
+
|
153
|
+
param_len = RARRAY_LEN(paramobj);
|
154
|
+
params = calloc((size_t)param_len + 1, sizeof(char *));
|
155
|
+
for (j = 0 ; j < param_len ; j++) {
|
156
|
+
VALUE entry = rb_ary_entry(paramobj, j);
|
157
|
+
const char *ptr = StringValueCStr(entry);
|
158
|
+
params[j] = ptr;
|
159
|
+
}
|
160
|
+
params[param_len] = 0 ;
|
161
|
+
|
162
|
+
errstr = rb_str_new(0, 0);
|
163
|
+
xsltSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
|
164
|
+
xmlSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
|
165
|
+
|
166
|
+
result = xsltApplyStylesheet(wrapper->ss, xml, params);
|
167
|
+
free(params);
|
168
|
+
|
169
|
+
xsltSetGenericErrorFunc(NULL, NULL);
|
170
|
+
xmlSetGenericErrorFunc(NULL, NULL);
|
171
|
+
|
172
|
+
parse_error_occurred = (Qfalse == rb_funcall(errstr, rb_intern("empty?"), 0));
|
173
|
+
|
174
|
+
if (parse_error_occurred) {
|
175
|
+
exception = rb_exc_new3(rb_eRuntimeError, errstr);
|
176
|
+
rb_exc_raise(exception);
|
177
|
+
}
|
178
|
+
|
179
|
+
return noko_xml_document_wrap((VALUE)0, result) ;
|
177
180
|
}
|
178
181
|
|
179
|
-
static void
|
182
|
+
static void
|
183
|
+
method_caller(xmlXPathParserContextPtr ctxt, int nargs)
|
180
184
|
{
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
+
VALUE handler;
|
186
|
+
const char *function_name;
|
187
|
+
xsltTransformContextPtr transform;
|
188
|
+
const xmlChar *functionURI;
|
185
189
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
+
transform = xsltXPathGetTransformContext(ctxt);
|
191
|
+
functionURI = ctxt->context->functionURI;
|
192
|
+
handler = (VALUE)xsltGetExtData(transform, functionURI);
|
193
|
+
function_name = (const char *)(ctxt->context->function);
|
190
194
|
|
191
|
-
|
195
|
+
Nokogiri_marshal_xpath_funcall_and_return_values(ctxt, nargs, handler, (const char *)function_name);
|
192
196
|
}
|
193
197
|
|
194
|
-
static void *
|
198
|
+
static void *
|
199
|
+
initFunc(xsltTransformContextPtr ctxt, const xmlChar *uri)
|
195
200
|
{
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
201
|
+
VALUE modules = rb_iv_get(mNokogiriXslt, "@modules");
|
202
|
+
VALUE obj = rb_hash_aref(modules, rb_str_new2((const char *)uri));
|
203
|
+
VALUE args = { Qfalse };
|
204
|
+
VALUE methods = rb_funcall(obj, rb_intern("instance_methods"), 1, args);
|
205
|
+
VALUE inst;
|
206
|
+
nokogiriXsltStylesheetTuple *wrapper;
|
207
|
+
int i;
|
208
|
+
|
209
|
+
for (i = 0; i < RARRAY_LEN(methods); i++) {
|
210
|
+
VALUE method_name = rb_obj_as_string(rb_ary_entry(methods, i));
|
211
|
+
xsltRegisterExtFunction(ctxt,
|
212
|
+
(unsigned char *)StringValueCStr(method_name), uri, method_caller);
|
213
|
+
}
|
214
|
+
|
215
|
+
Data_Get_Struct((VALUE)ctxt->style->_private, nokogiriXsltStylesheetTuple,
|
216
|
+
wrapper);
|
217
|
+
inst = rb_class_new_instance(0, NULL, obj);
|
218
|
+
rb_ary_push(wrapper->func_instances, inst);
|
219
|
+
|
220
|
+
return (void *)inst;
|
216
221
|
}
|
217
222
|
|
218
|
-
static void
|
219
|
-
|
223
|
+
static void
|
224
|
+
shutdownFunc(xsltTransformContextPtr ctxt,
|
225
|
+
const xmlChar *uri, void *data)
|
220
226
|
{
|
221
|
-
|
227
|
+
nokogiriXsltStylesheetTuple *wrapper;
|
222
228
|
|
223
|
-
|
224
|
-
|
229
|
+
Data_Get_Struct((VALUE)ctxt->style->_private, nokogiriXsltStylesheetTuple,
|
230
|
+
wrapper);
|
225
231
|
|
226
|
-
|
232
|
+
rb_ary_clear(wrapper->func_instances);
|
227
233
|
}
|
228
234
|
|
229
235
|
/*
|
@@ -232,32 +238,26 @@ static void shutdownFunc(xsltTransformContextPtr ctxt,
|
|
232
238
|
*
|
233
239
|
* Register a class that implements custom XSLT transformation functions.
|
234
240
|
*/
|
235
|
-
static VALUE
|
241
|
+
static VALUE
|
242
|
+
registr(VALUE self, VALUE uri, VALUE obj)
|
236
243
|
{
|
237
|
-
|
238
|
-
|
244
|
+
VALUE modules = rb_iv_get(self, "@modules");
|
245
|
+
if (NIL_P(modules)) { rb_raise(rb_eRuntimeError, "wtf! @modules isn't set"); }
|
239
246
|
|
240
|
-
|
241
|
-
|
242
|
-
|
247
|
+
rb_hash_aset(modules, uri, obj);
|
248
|
+
xsltRegisterExtModule((unsigned char *)StringValueCStr(uri), initFunc, shutdownFunc);
|
249
|
+
return self;
|
243
250
|
}
|
244
251
|
|
245
|
-
|
246
|
-
|
252
|
+
void
|
253
|
+
noko_init_xslt_stylesheet()
|
247
254
|
{
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
nokogiri = rb_define_module("Nokogiri");
|
252
|
-
xslt = rb_define_module_under(nokogiri, "XSLT");
|
253
|
-
klass = rb_define_class_under(xslt, "Stylesheet", rb_cObject);
|
254
|
-
|
255
|
-
rb_iv_set(xslt, "@modules", rb_hash_new());
|
255
|
+
rb_define_singleton_method(mNokogiriXslt, "register", registr, 2);
|
256
|
+
rb_iv_set(mNokogiriXslt, "@modules", rb_hash_new());
|
256
257
|
|
257
|
-
cNokogiriXsltStylesheet =
|
258
|
+
cNokogiriXsltStylesheet = rb_define_class_under(mNokogiriXslt, "Stylesheet", rb_cObject);
|
258
259
|
|
259
|
-
rb_define_singleton_method(
|
260
|
-
|
261
|
-
rb_define_method(
|
262
|
-
rb_define_method(klass, "transform", transform, -1);
|
260
|
+
rb_define_singleton_method(cNokogiriXsltStylesheet, "parse_stylesheet_doc", parse_stylesheet_doc, 1);
|
261
|
+
rb_define_method(cNokogiriXsltStylesheet, "serialize", serialize, 1);
|
262
|
+
rb_define_method(cNokogiriXsltStylesheet, "transform", transform, -1);
|
263
263
|
}
|
data/lib/nokogiri.rb
CHANGED
@@ -8,29 +8,8 @@ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
|
|
8
8
|
require 'nokogiri/jruby/dependencies'
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
RUBY_VERSION =~ /(\d+\.\d+)/
|
13
|
-
require "nokogiri/#{$1}/nokogiri"
|
14
|
-
rescue LoadError => e
|
15
|
-
if e.message =~ /GLIBC/
|
16
|
-
warn <<~EOM
|
11
|
+
require 'nokogiri/extension'
|
17
12
|
|
18
|
-
ERROR: It looks like you're trying to use Nokogiri as a precompiled native gem on a system with glibc < 2.17:
|
19
|
-
|
20
|
-
#{e.message}
|
21
|
-
|
22
|
-
If that's the case, then please install Nokogiri via the `ruby` platform gem:
|
23
|
-
gem install nokogiri --platform=ruby
|
24
|
-
or:
|
25
|
-
bundle config set force_ruby_platform true
|
26
|
-
|
27
|
-
Please visit https://nokogiri.org/tutorials/installing_nokogiri.html for more help.
|
28
|
-
|
29
|
-
EOM
|
30
|
-
raise e
|
31
|
-
end
|
32
|
-
require 'nokogiri/nokogiri'
|
33
|
-
end
|
34
13
|
require 'nokogiri/version'
|
35
14
|
require 'nokogiri/syntax_error'
|
36
15
|
require 'nokogiri/xml'
|
data/lib/nokogiri/css/parser.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# load the C or Java extension
|
4
|
+
begin
|
5
|
+
::RUBY_VERSION =~ /(\d+\.\d+)/
|
6
|
+
require "nokogiri/#{Regexp.last_match(1)}/nokogiri"
|
7
|
+
rescue LoadError => e
|
8
|
+
if e.message =~ /GLIBC/
|
9
|
+
warn(<<~EOM)
|
10
|
+
|
11
|
+
ERROR: It looks like you're trying to use Nokogiri as a precompiled native gem on a system with glibc < 2.17:
|
12
|
+
|
13
|
+
#{e.message}
|
14
|
+
|
15
|
+
If that's the case, then please install Nokogiri via the `ruby` platform gem:
|
16
|
+
gem install nokogiri --platform=ruby
|
17
|
+
or:
|
18
|
+
bundle config set force_ruby_platform true
|
19
|
+
|
20
|
+
Please visit https://nokogiri.org/tutorials/installing_nokogiri.html for more help.
|
21
|
+
|
22
|
+
EOM
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
require 'nokogiri/nokogiri'
|
26
|
+
end
|