nokogiri 1.4.3.1-java → 1.4.4-java
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.
- data/CHANGELOG.ja.rdoc +26 -0
- data/CHANGELOG.rdoc +26 -0
- data/Manifest.txt +3 -0
- data/README.ja.rdoc +0 -4
- data/README.rdoc +0 -4
- data/Rakefile +1 -0
- data/bin/nokogiri +6 -1
- data/ext/nokogiri/depend +358 -32
- data/ext/nokogiri/extconf.rb +1 -3
- data/ext/nokogiri/nokogiri.c +2 -0
- data/ext/nokogiri/nokogiri.h +7 -0
- data/ext/nokogiri/xml_dtd.c +2 -2
- data/ext/nokogiri/xml_io.c +2 -2
- data/ext/nokogiri/xml_node.c +31 -6
- data/ext/nokogiri/xml_node_set.c +1 -1
- data/ext/nokogiri/xml_sax_parser.c +1 -1
- data/ext/nokogiri/xml_sax_parser_context.c +40 -0
- data/ext/nokogiri/xml_xpath_context.c +33 -2
- data/ext/nokogiri/xslt_stylesheet.c +116 -4
- data/lib/nokogiri/css/generated_tokenizer.rb +1 -2
- data/lib/nokogiri/css/xpath_visitor.rb +15 -7
- data/lib/nokogiri/decorators/slop.rb +5 -3
- data/lib/nokogiri/ffi/libxml.rb +9 -0
- data/lib/nokogiri/ffi/structs/xml_parser_context.rb +2 -1
- data/lib/nokogiri/ffi/structs/xml_parser_input.rb +19 -0
- data/lib/nokogiri/ffi/xml/dtd.rb +2 -2
- data/lib/nokogiri/ffi/xml/node.rb +9 -4
- data/lib/nokogiri/ffi/xml/sax/parser_context.rb +12 -0
- data/lib/nokogiri/ffi/xml/xpath_context.rb +5 -0
- data/lib/nokogiri/ffi/xslt/stylesheet.rb +21 -1
- data/lib/nokogiri/html/document.rb +3 -3
- data/lib/nokogiri/html/document_fragment.rb +19 -17
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/document.rb +26 -1
- data/lib/nokogiri/xml/document_fragment.rb +2 -2
- data/lib/nokogiri/xml/dtd.rb +11 -0
- data/lib/nokogiri/xml/node.rb +156 -45
- data/lib/nokogiri/xml/node_set.rb +2 -2
- data/lib/nokogiri/xml/reader.rb +36 -0
- data/lib/nokogiri/xml/sax/document.rb +4 -2
- data/lib/nokogiri/xslt.rb +9 -5
- data/tasks/cross_compile.rb +24 -2
- data/test/css/test_parser.rb +29 -18
- data/test/decorators/test_slop.rb +16 -0
- data/test/html/test_document_fragment.rb +46 -3
- data/test/html/test_node.rb +9 -0
- data/test/xml/sax/test_parser.rb +11 -3
- data/test/xml/sax/test_parser_context.rb +50 -0
- data/test/xml/sax/test_push_parser.rb +18 -1
- data/test/xml/test_document_fragment.rb +14 -2
- data/test/xml/test_dtd.rb +15 -0
- data/test/xml/test_node.rb +31 -2
- data/test/xml/test_node_reparenting.rb +59 -31
- data/test/xml/test_node_set.rb +13 -0
- data/test/xml/test_xpath.rb +32 -0
- data/test/xslt/test_custom_functions.rb +94 -0
- metadata +495 -516
- data/ext/nokogiri/libcharset-1.dll +0 -0
- data/ext/nokogiri/libexslt.dll +0 -0
- data/ext/nokogiri/libiconv-2.dll +0 -0
- data/ext/nokogiri/libxml2.dll +0 -0
- data/ext/nokogiri/libxslt.dll +0 -0
- data/ext/nokogiri/zlib1.dll +0 -0
data/ext/nokogiri/extconf.rb
CHANGED
@@ -91,14 +91,12 @@ def asplode(lib)
|
|
91
91
|
abort "-----\n#{lib} is missing. please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies.\n-----"
|
92
92
|
end
|
93
93
|
|
94
|
-
# Use this with cross compiling
|
95
|
-
# PKG_CONFIG_PATH=/Users/apatterson/git/nokogiri/tmp/cross/lib/pkgconfig/ \
|
96
|
-
# rake cross compile RUBY_CC_VERSION=1.9.1
|
97
94
|
pkg_config('libxslt') if RUBY_PLATFORM =~ /mingw/
|
98
95
|
|
99
96
|
asplode "libxml2" unless find_header('libxml/parser.h')
|
100
97
|
asplode "libxslt" unless find_header('libxslt/xslt.h')
|
101
98
|
asplode "libexslt" unless find_header('libexslt/exslt.h')
|
99
|
+
asplode "libiconv" unless have_func('iconv_open', 'iconv.h') or have_library('iconv', 'iconv_open', 'iconv.h')
|
102
100
|
asplode "libxml2" unless find_library("#{lib_prefix}xml2", 'xmlParseDoc')
|
103
101
|
asplode "libxslt" unless find_library("#{lib_prefix}xslt", 'xsltParseStylesheetDoc')
|
104
102
|
asplode "libexslt" unless find_library("#{lib_prefix}exslt", 'exsltFuncRegister')
|
data/ext/nokogiri/nokogiri.c
CHANGED
@@ -30,12 +30,14 @@ int is_2_6_16(void)
|
|
30
30
|
|
31
31
|
void Init_nokogiri()
|
32
32
|
{
|
33
|
+
#ifndef __MACRUBY__
|
33
34
|
xmlMemSetup(
|
34
35
|
(xmlFreeFunc)ruby_xfree,
|
35
36
|
(xmlMallocFunc)ruby_xmalloc,
|
36
37
|
(xmlReallocFunc)ruby_xrealloc,
|
37
38
|
strdup
|
38
39
|
);
|
40
|
+
#endif
|
39
41
|
|
40
42
|
mNokogiri = rb_define_module("Nokogiri");
|
41
43
|
mNokogiriXml = rb_define_module_under(mNokogiri, "XML");
|
data/ext/nokogiri/nokogiri.h
CHANGED
@@ -27,6 +27,7 @@ int vasprintf (char **strp, const char *fmt, va_list ap);
|
|
27
27
|
#include <libxml/HTMLparser.h>
|
28
28
|
#include <libxml/HTMLtree.h>
|
29
29
|
#include <libxml/relaxng.h>
|
30
|
+
#include <libxslt/extensions.h>
|
30
31
|
#include <ruby.h>
|
31
32
|
|
32
33
|
#ifdef HAVE_RUBY_ENCODING_H
|
@@ -134,6 +135,8 @@ extern VALUE mNokogiriXslt ;
|
|
134
135
|
#define NOKOGIRI_DEBUG_START(p)
|
135
136
|
#define NOKOGIRI_DEBUG_END(p)
|
136
137
|
|
138
|
+
#endif
|
139
|
+
|
137
140
|
#ifndef RSTRING_PTR
|
138
141
|
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
139
142
|
#endif
|
@@ -150,6 +153,10 @@ extern VALUE mNokogiriXslt ;
|
|
150
153
|
#define RARRAY_LEN(a) RARRAY(a)->len
|
151
154
|
#endif
|
152
155
|
|
156
|
+
#ifndef __builtin_expect
|
157
|
+
# if defined(__GNUC__)
|
158
|
+
# define __builtin_expect(expr, c) __builtin_expect((long)(expr), (long)(c))
|
159
|
+
# endif
|
153
160
|
#endif
|
154
161
|
|
155
162
|
#endif
|
data/ext/nokogiri/xml_dtd.c
CHANGED
@@ -84,10 +84,10 @@ static VALUE attributes(VALUE self)
|
|
84
84
|
|
85
85
|
Data_Get_Struct(self, xmlDtd, dtd);
|
86
86
|
|
87
|
-
if(!dtd->attributes) return Qnil;
|
88
|
-
|
89
87
|
hash = rb_hash_new();
|
90
88
|
|
89
|
+
if(!dtd->attributes) return hash;
|
90
|
+
|
91
91
|
xmlHashScan((xmlHashTablePtr)dtd->attributes, element_copier, (void *)hash);
|
92
92
|
|
93
93
|
return hash;
|
data/ext/nokogiri/xml_io.c
CHANGED
@@ -8,14 +8,14 @@ int io_read_callback(void * ctx, char * buffer, int len) {
|
|
8
8
|
|
9
9
|
if(NIL_P(string)) return 0;
|
10
10
|
|
11
|
-
memcpy(buffer, StringValuePtr(string), (
|
11
|
+
memcpy(buffer, StringValuePtr(string), (size_t)RSTRING_LEN(string));
|
12
12
|
|
13
13
|
return (int)RSTRING_LEN(string);
|
14
14
|
}
|
15
15
|
|
16
16
|
int io_write_callback(void * ctx, char * buffer, int len) {
|
17
17
|
VALUE io = (VALUE)ctx;
|
18
|
-
VALUE string = rb_str_new(buffer, len);
|
18
|
+
VALUE string = rb_str_new(buffer, (long)len);
|
19
19
|
|
20
20
|
rb_funcall(io, id_write, 1, string);
|
21
21
|
return len;
|
data/ext/nokogiri/xml_node.c
CHANGED
@@ -251,7 +251,13 @@ static VALUE encode_special_chars(VALUE self, VALUE string)
|
|
251
251
|
* call-seq:
|
252
252
|
* create_internal_subset(name, external_id, system_id)
|
253
253
|
*
|
254
|
-
* Create
|
254
|
+
* Create the internal subset of a document.
|
255
|
+
*
|
256
|
+
* doc.create_internal_subset("chapter", "-//OASIS//DTD DocBook XML//EN", "chapter.dtd")
|
257
|
+
* # => <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML//EN" "chapter.dtd">
|
258
|
+
*
|
259
|
+
* doc.create_internal_subset("chapter", nil, "chapter.dtd")
|
260
|
+
* # => <!DOCTYPE chapter SYSTEM "chapter.dtd">
|
255
261
|
*/
|
256
262
|
static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
|
257
263
|
{
|
@@ -377,6 +383,8 @@ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
377
383
|
dup = xmlDocCopyNode(node, node->doc, (int)NUM2INT(level));
|
378
384
|
if(dup == NULL) return Qnil;
|
379
385
|
|
386
|
+
NOKOGIRI_ROOT_NODE(dup);
|
387
|
+
|
380
388
|
return Nokogiri_wrap_xml_node(rb_obj_class(self), dup);
|
381
389
|
}
|
382
390
|
|
@@ -774,7 +782,8 @@ static VALUE attribute_nodes(VALUE self)
|
|
774
782
|
* call-seq:
|
775
783
|
* namespace()
|
776
784
|
*
|
777
|
-
* returns the
|
785
|
+
* returns the default namespace set on this node (as with an "xmlns="
|
786
|
+
* attribute), as a Namespace object.
|
778
787
|
*/
|
779
788
|
static VALUE namespace(VALUE self)
|
780
789
|
{
|
@@ -791,7 +800,7 @@ static VALUE namespace(VALUE self)
|
|
791
800
|
* call-seq:
|
792
801
|
* namespace_definitions()
|
793
802
|
*
|
794
|
-
* returns
|
803
|
+
* returns namespaces defined on self element directly, as an array of Namespace objects. Includes both a default namespace (as in"xmlns="), and prefixed namespaces (as in "xmlns:prefix=").
|
795
804
|
*/
|
796
805
|
static VALUE namespace_definitions(VALUE self)
|
797
806
|
{
|
@@ -820,8 +829,10 @@ static VALUE namespace_definitions(VALUE self)
|
|
820
829
|
* call-seq:
|
821
830
|
* namespace_scopes()
|
822
831
|
*
|
823
|
-
*
|
824
|
-
*
|
832
|
+
* returns namespaces in scope for self -- those defined on self element
|
833
|
+
* directly or any ancestor node -- as an array of Namespace objects. Default
|
834
|
+
* namespaces ("xmlns=" style) for self are included in this array; Default
|
835
|
+
* namespaces for ancestors, however, are not. See also #namespaces
|
825
836
|
*/
|
826
837
|
static VALUE namespace_scopes(VALUE self)
|
827
838
|
{
|
@@ -1045,7 +1056,12 @@ static VALUE line(VALUE self)
|
|
1045
1056
|
* call-seq:
|
1046
1057
|
* add_namespace_definition(prefix, href)
|
1047
1058
|
*
|
1048
|
-
* Adds a namespace definition with +prefix+ using +href+
|
1059
|
+
* Adds a namespace definition with +prefix+ using +href+ value. The result is
|
1060
|
+
* as if parsed XML for this node had included an attribute
|
1061
|
+
* 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
|
1062
|
+
* added by passing 'nil' for prefix. Namespaces added this way will not
|
1063
|
+
* show up in #attributes, but they will be included as an xmlns attribute
|
1064
|
+
* when the node is serialized to XML.
|
1049
1065
|
*/
|
1050
1066
|
static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
|
1051
1067
|
{
|
@@ -1155,6 +1171,7 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1155
1171
|
{
|
1156
1172
|
xmlNodePtr node;
|
1157
1173
|
xmlNodePtr list;
|
1174
|
+
xmlNodePtr child_iter;
|
1158
1175
|
xmlNodeSetPtr set;
|
1159
1176
|
xmlParserErrors error;
|
1160
1177
|
VALUE doc, err;
|
@@ -1180,6 +1197,14 @@ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1180
1197
|
(int)NUM2INT(_options),
|
1181
1198
|
&list);
|
1182
1199
|
|
1200
|
+
/* make sure parent/child pointers are coherent so an unlink will work properly (#331) */
|
1201
|
+
child_iter = node->doc->children ;
|
1202
|
+
while (child_iter) {
|
1203
|
+
if (child_iter->parent != (xmlNodePtr)node->doc)
|
1204
|
+
child_iter->parent = (xmlNodePtr)node->doc ;
|
1205
|
+
child_iter = child_iter->next ;
|
1206
|
+
}
|
1207
|
+
|
1183
1208
|
#ifndef HTML_PARSE_NOIMPLIED
|
1184
1209
|
htmlHandleOmittedElem(1);
|
1185
1210
|
#endif
|
data/ext/nokogiri/xml_node_set.c
CHANGED
@@ -257,7 +257,7 @@ static VALUE slice(int argc, VALUE *argv, VALUE self)
|
|
257
257
|
}
|
258
258
|
|
259
259
|
/* if arg is Range */
|
260
|
-
switch (rb_range_beg_len(arg, &beg, &len, node_set->nodeNr, 0)) {
|
260
|
+
switch (rb_range_beg_len(arg, &beg, &len, (long)node_set->nodeNr, 0)) {
|
261
261
|
case Qfalse:
|
262
262
|
break;
|
263
263
|
case Qnil:
|
@@ -238,7 +238,7 @@ static void deallocate(xmlSAXHandlerPtr handler)
|
|
238
238
|
|
239
239
|
static VALUE allocate(VALUE klass)
|
240
240
|
{
|
241
|
-
xmlSAXHandlerPtr handler = calloc(1, sizeof(xmlSAXHandler));
|
241
|
+
xmlSAXHandlerPtr handler = calloc((size_t)1, sizeof(xmlSAXHandler));
|
242
242
|
|
243
243
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
244
244
|
|
@@ -140,6 +140,44 @@ static VALUE get_replace_entities(VALUE self)
|
|
140
140
|
return Qtrue;
|
141
141
|
}
|
142
142
|
|
143
|
+
/*
|
144
|
+
* call-seq: line
|
145
|
+
*
|
146
|
+
* Get the current line the parser context is processing.
|
147
|
+
*/
|
148
|
+
static VALUE line(VALUE self)
|
149
|
+
{
|
150
|
+
xmlParserCtxtPtr ctxt;
|
151
|
+
xmlParserInputPtr io;
|
152
|
+
|
153
|
+
Data_Get_Struct(self, xmlParserCtxt, ctxt);
|
154
|
+
|
155
|
+
io = ctxt->input;
|
156
|
+
if(io)
|
157
|
+
return INT2NUM(io->line);
|
158
|
+
|
159
|
+
return Qnil;
|
160
|
+
}
|
161
|
+
|
162
|
+
/*
|
163
|
+
* call-seq: column
|
164
|
+
*
|
165
|
+
* Get the current column the parser context is processing.
|
166
|
+
*/
|
167
|
+
static VALUE column(VALUE self)
|
168
|
+
{
|
169
|
+
xmlParserCtxtPtr ctxt;
|
170
|
+
xmlParserInputPtr io;
|
171
|
+
|
172
|
+
Data_Get_Struct(self, xmlParserCtxt, ctxt);
|
173
|
+
|
174
|
+
io = ctxt->input;
|
175
|
+
if(io)
|
176
|
+
return INT2NUM(io->col);
|
177
|
+
|
178
|
+
return Qnil;
|
179
|
+
}
|
180
|
+
|
143
181
|
void init_xml_sax_parser_context()
|
144
182
|
{
|
145
183
|
VALUE nokogiri = rb_define_module("Nokogiri");
|
@@ -156,4 +194,6 @@ void init_xml_sax_parser_context()
|
|
156
194
|
rb_define_method(klass, "parse_with", parse_with, 1);
|
157
195
|
rb_define_method(klass, "replace_entities=", set_replace_entities, 1);
|
158
196
|
rb_define_method(klass, "replace_entities", get_replace_entities, 0);
|
197
|
+
rb_define_method(klass, "line", line, 0);
|
198
|
+
rb_define_method(klass, "column", column, 0);
|
159
199
|
}
|
@@ -27,6 +27,28 @@ static VALUE register_ns(VALUE self, VALUE prefix, VALUE uri)
|
|
27
27
|
return self;
|
28
28
|
}
|
29
29
|
|
30
|
+
/*
|
31
|
+
* call-seq:
|
32
|
+
* register_variable(name, value)
|
33
|
+
*
|
34
|
+
* Register the variable +name+ with +value+.
|
35
|
+
*/
|
36
|
+
static VALUE register_variable(VALUE self, VALUE name, VALUE value)
|
37
|
+
{
|
38
|
+
xmlXPathContextPtr ctx;
|
39
|
+
xmlXPathObjectPtr xmlValue;
|
40
|
+
Data_Get_Struct(self, xmlXPathContext, ctx);
|
41
|
+
|
42
|
+
xmlValue = xmlXPathNewCString(StringValuePtr(value));
|
43
|
+
|
44
|
+
xmlXPathRegisterVariable( ctx,
|
45
|
+
(const xmlChar *)StringValuePtr(name),
|
46
|
+
xmlValue
|
47
|
+
);
|
48
|
+
|
49
|
+
return self;
|
50
|
+
}
|
51
|
+
|
30
52
|
static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
|
31
53
|
{
|
32
54
|
VALUE xpath_handler = Qnil;
|
@@ -46,7 +68,11 @@ static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
|
|
46
68
|
|
47
69
|
xpath_handler = (VALUE)(ctx->context->userData);
|
48
70
|
|
49
|
-
argv = (VALUE *)calloc((
|
71
|
+
argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE));
|
72
|
+
for (i = 0 ; i < nargs ; ++i) {
|
73
|
+
rb_gc_register_address(&argv[i]);
|
74
|
+
}
|
75
|
+
|
50
76
|
doc = DOC_RUBY_OBJECT(ctx->context->doc);
|
51
77
|
|
52
78
|
i = nargs - 1;
|
@@ -77,6 +103,10 @@ static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
|
|
77
103
|
nargs,
|
78
104
|
argv
|
79
105
|
);
|
106
|
+
|
107
|
+
for (i = 0 ; i < nargs ; ++i) {
|
108
|
+
rb_gc_unregister_address(&argv[i]);
|
109
|
+
}
|
80
110
|
free(argv);
|
81
111
|
|
82
112
|
switch(TYPE(result)) {
|
@@ -156,7 +186,7 @@ static void xpath_generic_exception_handler(void * ctx, const char *msg, ...)
|
|
156
186
|
|
157
187
|
/*
|
158
188
|
* call-seq:
|
159
|
-
* evaluate(search_path)
|
189
|
+
* evaluate(search_path, handler = nil)
|
160
190
|
*
|
161
191
|
* Evaluate the +search_path+ returning an XML::XPath object.
|
162
192
|
*/
|
@@ -274,5 +304,6 @@ void init_xml_xpath_context(void)
|
|
274
304
|
|
275
305
|
rb_define_singleton_method(klass, "new", new, 1);
|
276
306
|
rb_define_method(klass, "evaluate", evaluate, -1);
|
307
|
+
rb_define_method(klass, "register_variable", register_variable, 2);
|
277
308
|
rb_define_method(klass, "register_ns", register_ns, 2);
|
278
309
|
}
|
@@ -5,6 +5,8 @@
|
|
5
5
|
#include <libxslt/transform.h>
|
6
6
|
#include <libexslt/exslt.h>
|
7
7
|
|
8
|
+
VALUE xslt;
|
9
|
+
|
8
10
|
int vasprintf (char **strp, const char *fmt, va_list ap);
|
9
11
|
|
10
12
|
static void dealloc(xsltStylesheetPtr doc)
|
@@ -24,7 +26,7 @@ static void xslt_generic_error_handler(void * ctx, const char *msg, ...)
|
|
24
26
|
vasprintf(&message, msg, args);
|
25
27
|
va_end(args);
|
26
28
|
|
27
|
-
|
29
|
+
rb_exc_raise(rb_exc_new2(rb_eRuntimeError, message));
|
28
30
|
}
|
29
31
|
|
30
32
|
/*
|
@@ -97,7 +99,7 @@ static VALUE transform(int argc, VALUE* argv, VALUE self)
|
|
97
99
|
long param_len, j ;
|
98
100
|
|
99
101
|
rb_scan_args(argc, argv, "11", &xmldoc, ¶mobj);
|
100
|
-
if (NIL_P(paramobj)) { paramobj = rb_ary_new2(
|
102
|
+
if (NIL_P(paramobj)) { paramobj = rb_ary_new2(0L) ; }
|
101
103
|
|
102
104
|
/* handle hashes as arguments. */
|
103
105
|
if(T_HASH == TYPE(paramobj)) {
|
@@ -124,19 +126,129 @@ static VALUE transform(int argc, VALUE* argv, VALUE self)
|
|
124
126
|
|
125
127
|
if (!result) rb_raise(rb_eRuntimeError, "could not perform xslt transform on document");
|
126
128
|
|
127
|
-
return Nokogiri_wrap_xml_document(0, result) ;
|
129
|
+
return Nokogiri_wrap_xml_document((VALUE)0, result) ;
|
130
|
+
}
|
131
|
+
|
132
|
+
static void method_caller(xmlXPathParserContextPtr ctxt, int nargs)
|
133
|
+
{
|
134
|
+
const xmlChar * function;
|
135
|
+
const xmlChar * functionURI;
|
136
|
+
size_t i, count;
|
137
|
+
|
138
|
+
xsltTransformContextPtr transform;
|
139
|
+
xmlXPathObjectPtr xpath;
|
140
|
+
VALUE obj;
|
141
|
+
VALUE *args;
|
142
|
+
|
143
|
+
transform = xsltXPathGetTransformContext(ctxt);
|
144
|
+
|
145
|
+
function = ctxt->context->function;
|
146
|
+
functionURI = ctxt->context->functionURI;
|
147
|
+
obj = (VALUE)xsltGetExtData(transform, functionURI);
|
148
|
+
|
149
|
+
count = (size_t)ctxt->valueNr;
|
150
|
+
args = calloc(count, sizeof(VALUE *));
|
151
|
+
|
152
|
+
for(i = 0; i < count; i++) {
|
153
|
+
VALUE thing;
|
154
|
+
|
155
|
+
xpath = valuePop(ctxt);
|
156
|
+
switch(xpath->type) {
|
157
|
+
case XPATH_STRING:
|
158
|
+
thing = NOKOGIRI_STR_NEW2(xpath->stringval);
|
159
|
+
break;
|
160
|
+
case XPATH_NODESET:
|
161
|
+
if(NULL == xpath->nodesetval) {
|
162
|
+
thing = Nokogiri_wrap_xml_node_set(
|
163
|
+
xmlXPathNodeSetCreate(NULL),
|
164
|
+
DOC_RUBY_OBJECT(ctxt->context->doc));
|
165
|
+
} else {
|
166
|
+
thing = Nokogiri_wrap_xml_node_set(xpath->nodesetval,
|
167
|
+
DOC_RUBY_OBJECT(ctxt->context->doc));
|
168
|
+
}
|
169
|
+
break;
|
170
|
+
default:
|
171
|
+
rb_raise(rb_eRuntimeError, "do not handle type: %d", xpath->type);
|
172
|
+
}
|
173
|
+
args[i] = thing;
|
174
|
+
}
|
175
|
+
VALUE result = rb_funcall3(obj, rb_intern((const char *)function), (int)count, args);
|
176
|
+
switch(TYPE(result)) {
|
177
|
+
case T_FLOAT:
|
178
|
+
case T_BIGNUM:
|
179
|
+
case T_FIXNUM:
|
180
|
+
xmlXPathReturnNumber(ctxt, NUM2DBL(result));
|
181
|
+
break;
|
182
|
+
case T_STRING:
|
183
|
+
xmlXPathReturnString(
|
184
|
+
ctxt,
|
185
|
+
xmlStrdup((xmlChar *)StringValuePtr(result))
|
186
|
+
);
|
187
|
+
break;
|
188
|
+
case T_TRUE:
|
189
|
+
xmlXPathReturnTrue(ctxt);
|
190
|
+
break;
|
191
|
+
case T_FALSE:
|
192
|
+
xmlXPathReturnFalse(ctxt);
|
193
|
+
break;
|
194
|
+
case T_NIL:
|
195
|
+
break;
|
196
|
+
default:
|
197
|
+
rb_raise(rb_eRuntimeError, "Invalid return type");
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
static void * initFunc(xsltTransformContextPtr ctxt, const xmlChar *uri)
|
202
|
+
{
|
203
|
+
VALUE modules = rb_iv_get(xslt, "@modules");
|
204
|
+
VALUE obj = rb_hash_aref(modules, rb_str_new2((const char *)uri));
|
205
|
+
VALUE args = { Qfalse };
|
206
|
+
VALUE methods = rb_funcall(obj, rb_intern("instance_methods"), 1, args);
|
207
|
+
int i;
|
208
|
+
|
209
|
+
for(i = 0; i < RARRAY_LEN(methods); i++) {
|
210
|
+
VALUE method_name = rb_obj_as_string(RARRAY_PTR(methods)[i]);
|
211
|
+
xsltRegisterExtFunction(ctxt,
|
212
|
+
(unsigned char *)StringValuePtr(method_name), uri, method_caller);
|
213
|
+
}
|
214
|
+
|
215
|
+
return (void *)rb_class_new_instance(0, NULL, obj);
|
216
|
+
}
|
217
|
+
|
218
|
+
static void shutdownFunc(xsltTransformContextPtr ctxt,
|
219
|
+
const xmlChar *uri, void *data)
|
220
|
+
{
|
221
|
+
}
|
222
|
+
|
223
|
+
/*
|
224
|
+
* call-seq:
|
225
|
+
* register(uri, custom_handler_class)
|
226
|
+
*
|
227
|
+
* Register a class that implements custom XLST transformation functions.
|
228
|
+
*/
|
229
|
+
static VALUE registr(VALUE self, VALUE uri, VALUE obj)
|
230
|
+
{
|
231
|
+
VALUE modules = rb_iv_get(self, "@modules");
|
232
|
+
if(NIL_P(modules)) rb_raise(rb_eRuntimeError, "wtf! @modules isn't set");
|
233
|
+
|
234
|
+
rb_hash_aset(modules, uri, obj);
|
235
|
+
xsltRegisterExtModule((unsigned char *)StringValuePtr(uri), initFunc, shutdownFunc);
|
236
|
+
return self;
|
128
237
|
}
|
129
238
|
|
130
239
|
VALUE cNokogiriXsltStylesheet ;
|
131
240
|
void init_xslt_stylesheet()
|
132
241
|
{
|
133
242
|
VALUE nokogiri = rb_define_module("Nokogiri");
|
134
|
-
|
243
|
+
xslt = rb_define_module_under(nokogiri, "XSLT");
|
135
244
|
VALUE klass = rb_define_class_under(xslt, "Stylesheet", rb_cObject);
|
136
245
|
|
246
|
+
rb_iv_set(xslt, "@modules", rb_hash_new());
|
247
|
+
|
137
248
|
cNokogiriXsltStylesheet = klass;
|
138
249
|
|
139
250
|
rb_define_singleton_method(klass, "parse_stylesheet_doc", parse_stylesheet_doc, 1);
|
251
|
+
rb_define_singleton_method(xslt, "register", registr, 2);
|
140
252
|
rb_define_method(klass, "serialize", serialize, 1);
|
141
253
|
rb_define_method(klass, "transform", transform, -1);
|
142
254
|
}
|