ruby-xslt 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
2
+ <nodes>
3
+ <node number="1">Hello, </node>
4
+ <node number="2">World!</node>
5
+ </nodes>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
3
+ <xsl:output method="text" encoding="iso-8859-1" indent="no"/>
4
+ <xsl:param name="p1"/>
5
+ <xsl:param name="p2"/>
6
+
7
+ <xsl:template match="/">
8
+ p1:<xsl:value-of select="$p1"/>&#10;
9
+ p2:<xsl:value-of select="$p2"/>&#10;
10
+ <xsl:apply-templates/>
11
+ </xsl:template>
12
+
13
+ <xsl:template match="node">
14
+ <xsl:value-of select="."/>(<xsl:value-of select="@number"/>)&#10;
15
+ </xsl:template>
16
+
17
+ </xsl:stylesheet>
18
+
@@ -0,0 +1,18 @@
1
+ require "../xslt"
2
+
3
+ class XML::XSLT
4
+ def round_trip( arg )
5
+ arg
6
+ end
7
+ def type( arg )
8
+ arg.class.to_s
9
+ end
10
+ end
11
+
12
+ xslt = XML::XSLT.new()
13
+ xslt.xsl = "functions.xsl"
14
+ xslt.xml = "test.xml"
15
+ XML::XSLT.extFunction("round-trip", "http://test.none", xslt)
16
+ XML::XSLT.extFunction("type", "http://test.none", xslt)
17
+
18
+ puts xslt.serve
@@ -0,0 +1,13 @@
1
+ require "../xslt"
2
+
3
+ xslt = XML::XSLT.new()
4
+ xslt.xsl = "test.xsl"
5
+ xslt.xml = "test.xml"
6
+ xslt.parameters = { "p1" => "the first parameter ...",
7
+ "p2" => "'and the second one!'" }
8
+ #xslt.save("test.html")
9
+ puts xslt.serve
10
+ xslt.parameters = { "p1" => "Ruby...",
11
+ "p2" => "'...is cool !'" }
12
+ #xslt.save("test.html")
13
+ puts xslt.serve
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/ruby -w
2
+ # See the LICENSE file for copyright and distribution information
3
+
4
+ require "mkmf"
5
+
6
+ def help
7
+ print <<HELP
8
+ "extconf.rb" configures this package to adapt to many kinds of systems.
9
+
10
+ Usage: ruby extconf.rb [OPTION]...
11
+
12
+ Configuration:
13
+ --help display this help and exit
14
+
15
+ --with-xslt-lib=PATH
16
+ --with-xslt-include=PATH
17
+ --with-xslt-dir=PATH specify the directory name for the libxslt include
18
+ files and/or library
19
+
20
+ --enable-error-handler enables a VERY crude error handler. Error messages
21
+ are appended to the class variable XML::XSLT and can
22
+ be accessed with the class method XML::XSLT.errors
23
+ (will change in a future version)
24
+ --disable-exslt disables libexslt support <http://exslt.org/>
25
+
26
+ --enable-debug compile with memwatch
27
+ <http://www.linkdata.se/sourcecode.html>
28
+
29
+ HELP
30
+ end
31
+
32
+ if ARGV.include?( "--help" )
33
+ help()
34
+ exit 0
35
+ end
36
+
37
+ if enable_config("debug", false)
38
+ File.symlink( "debug/memwatch.h", "memwatch.h" ) if( ! File.exist?("memwatch.h") )
39
+ File.symlink( "debug/memwatch.c", "memwatch.c" ) if( ! File.exist?("memwatch.c") )
40
+ $CFLAGS += " -DMEMWATCH -D__DEBUG__"
41
+ end
42
+
43
+ if enable_config("error-handler", false)
44
+ $CFLAGS += " -DUSE_ERROR_HANDLER"
45
+ end
46
+
47
+ $LIBPATH.push(Config::CONFIG['libdir'])
48
+
49
+ def crash(str)
50
+ printf(" extconf failure: %s\n", str)
51
+ exit 1
52
+ end
53
+
54
+ #unless have_library("z", "inflate")
55
+ # crash("need zlib")
56
+ #else
57
+ # $defs.push('-DHAVE_ZLIB_H')
58
+ #end
59
+
60
+ if dir_config( "xslt" ) != [nil, nil]
61
+ inc, lib = dir_config( 'xslt' )
62
+ $LDFLAGS << " -L#{lib} -lxslt -lxml2 -lz -lpthread -liconv -lm"
63
+ $CFLAGS << " -I#{inc}"
64
+ elsif ex = find_executable( "xslt-config" )
65
+ $LDFLAGS << ' ' + `#{ex} --libs`.chomp
66
+ $CFLAGS << ' ' + `#{ex} --cflags`.chomp
67
+ else
68
+ crash(<<EOL)
69
+ need libxslt.
70
+
71
+ Install the library or try one of the following options to extconf.rb:
72
+
73
+ --with-xslt-lib=/path/to/libxslt/lib
74
+ --with-xslt-include=/path/to/libxslt/include
75
+ EOL
76
+ end
77
+
78
+ if enable_config("exslt", true)
79
+ $LDFLAGS << " -lexslt"
80
+ $CFLAGS += " -DUSE_EXSLT"
81
+ end
82
+
83
+ $CFLAGS = '-g -Wall ' + $CFLAGS
84
+
85
+ puts "compile with : "
86
+ puts " CFLAGS = #{$CFLAGS}"
87
+ puts " LDFLAGS = #{$LDFLAGS}"
88
+ puts
89
+
90
+ create_header()
91
+ create_makefile("xml/xslt")
92
+
93
+ ###### Modify Makefile: #######
94
+ File.rename( "Makefile", "Makefile.orig" )
95
+ oldmkfl = File.open( "Makefile.orig" )
96
+ newmkfl = File.open( "Makefile", "w" )
97
+ oldmkfl.each_line{ |line|
98
+ case(line)
99
+ when /^all:/
100
+ newmkfl.puts(line)
101
+ newmkfl.puts("")
102
+ newmkfl.puts("test: all") # insert the "test" target
103
+ newmkfl.puts("\t\t@cd tests && ruby test.rb && cd ..")
104
+ newmkfl.puts("doc: all") # insert the "doc" target
105
+ newmkfl.puts("\t\t@rdoc -S -t \"Ruby/XSLT Documentation\" README AUTHORS ChangeLog xslt.c")
106
+ when /^distclean:/
107
+ newmkfl.puts(line)
108
+ newmkfl.puts("\t\t@-$(RM) memwatch.h memwatch.c Makefile.orig")
109
+ newmkfl.puts("\t\t@-$(RM)r doc")
110
+ else
111
+ newmkfl.puts(line)
112
+ end
113
+ }
114
+ newmkfl.close
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation; either version 2 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "xslt.h"
20
+
21
+ extern VALUE mXML;
22
+ extern VALUE cXSLT;
23
+
24
+ /**
25
+ * external function support, patch from :
26
+ *
27
+ * Brendan Taylor
28
+ * whateley@gmail.com
29
+ *
30
+ */
31
+
32
+
33
+ /* converts an xmlXPathObjectPtr to a Ruby VALUE
34
+ * number -> float
35
+ * boolean -> boolean
36
+ * string -> string
37
+ * nodeset -> an array of REXML::Elements
38
+ */
39
+ VALUE xpathObj2value(xmlXPathObjectPtr obj, xmlDocPtr doc)
40
+ {
41
+ VALUE ret = Qnil;
42
+
43
+ if (obj == NULL) {
44
+ return ret;
45
+ }
46
+
47
+ switch (obj->type) {
48
+ case XPATH_NODESET:
49
+ rb_require("rexml/document");
50
+ ret = rb_ary_new();
51
+
52
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
53
+ xmlBufferPtr buff = xmlBufferCreate();
54
+ xmlNodePtr node;
55
+ int i;
56
+
57
+ // this assumes all the nodes are elements, which is a bad idea
58
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
59
+ node = obj->nodesetval->nodeTab[i];
60
+
61
+ if( node->type == XML_ELEMENT_NODE ) {
62
+ xmlNodeDump(buff, doc, node, 0, 0);
63
+
64
+ VALUE cREXML = rb_const_get(rb_cObject, rb_intern("REXML"));
65
+ VALUE cDocument = rb_const_get(cREXML, rb_intern("Document"));
66
+ VALUE rDocument = rb_funcall(cDocument, rb_intern("new"), 1,rb_str_new2((char *)buff->content));
67
+ VALUE rElement = rb_funcall(rDocument, rb_intern("root"), 0);
68
+
69
+ rb_ary_push(ret, rElement);
70
+
71
+ // empty the buffer (xmlNodeDump appends rather than replaces)
72
+ xmlBufferEmpty(buff);
73
+ } else if ( node->type == XML_TEXT_NODE ) {
74
+ rb_ary_push(ret, rb_str_new2((char *)node->content));
75
+ }
76
+ }
77
+ xmlBufferFree(buff);
78
+ }
79
+ break;
80
+ case XPATH_BOOLEAN:
81
+ ret = obj->boolval ? Qtrue : Qfalse;
82
+ break;
83
+ case XPATH_NUMBER:
84
+ ret = rb_float_new(obj->floatval);
85
+ break;
86
+ case XPATH_STRING:
87
+ ret = rb_str_new2((char *) obj->stringval);
88
+ break;
89
+ /* these cases were in libxslt's python bindings, but i don't know what they are, so i'll leave them alone */
90
+ case XPATH_XSLT_TREE:
91
+ case XPATH_POINT:
92
+ case XPATH_RANGE:
93
+ case XPATH_LOCATIONSET:
94
+ default:
95
+ rb_warning("xpathObj2value: can't convert XPath object type %d to Ruby object\n", obj->type );
96
+ }
97
+ xmlXPathFreeObject(obj);
98
+ return ret;
99
+ }
100
+
101
+ /*
102
+ * converts a Ruby VALUE to an xmlXPathObjectPtr
103
+ * boolean -> boolean
104
+ * number -> number
105
+ * string -> escaped string
106
+ * array -> array of parsed nodes
107
+ */
108
+ xmlXPathObjectPtr value2xpathObj (VALUE val) {
109
+ xmlXPathObjectPtr ret = NULL;
110
+
111
+ switch (TYPE(val)) {
112
+ case T_TRUE:
113
+ case T_FALSE:
114
+ ret = xmlXPathNewBoolean(RTEST(val));
115
+ break;
116
+ case T_FIXNUM:
117
+ case T_FLOAT:
118
+ ret = xmlXPathNewFloat(NUM2DBL(val));
119
+ break;
120
+ case T_STRING:
121
+ {
122
+ xmlChar *str;
123
+
124
+ // we need the Strdup (this is the major bugfix for 0.8.1)
125
+ str = xmlStrdup((const xmlChar *) STR2CSTR(val));
126
+ ret = xmlXPathWrapString(str);
127
+ }
128
+ break;
129
+ case T_NIL:
130
+ ret = xmlXPathNewNodeSet(NULL);
131
+ break;
132
+ case T_ARRAY: {
133
+ int i,j;
134
+ ret = xmlXPathNewNodeSet(NULL);
135
+
136
+ for(i = RARRAY(val)->len; i > 0; i--) {
137
+ xmlXPathObjectPtr obj = value2xpathObj( rb_ary_shift( val ) );
138
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
139
+ for(j = 0; j < obj->nodesetval->nodeNr; j++) {
140
+ xmlXPathNodeSetAdd( ret->nodesetval, obj->nodesetval->nodeTab[j] );
141
+ }
142
+ }
143
+ }
144
+ break; }
145
+ case T_DATA:
146
+ case T_OBJECT: {
147
+ if( strcmp( getRubyObjectName( val ), "REXML::Document" ) == 0 || strcmp(getRubyObjectName( val ), "REXML::Element") == 0 ) {
148
+
149
+ VALUE to_s = rb_funcall( val, rb_intern( "to_s" ), 0 );
150
+ xmlDocPtr doc = xmlParseDoc((xmlChar *) STR2CSTR(to_s));
151
+
152
+ ret = xmlXPathNewNodeSet((xmlNode *)doc->children);
153
+ break;
154
+ } else if( strcmp( getRubyObjectName( val ), "REXML::Text" ) == 0 ) {
155
+ VALUE to_s = rb_funcall( val, rb_intern( "to_s" ), 0 );
156
+
157
+ xmlChar *str;
158
+
159
+ str = xmlStrdup((const xmlChar *) STR2CSTR(to_s));
160
+ ret = xmlXPathWrapString(str);
161
+ break;
162
+ }
163
+ // this drops through so i can reuse the error message
164
+ }
165
+ default:
166
+ rb_warning( "value2xpathObj: can't convert class %s to XPath object\n", getRubyObjectName(val));
167
+ return NULL;
168
+ }
169
+
170
+ return ret;
171
+ }
172
+
173
+ /*
174
+ * chooses what registered function to call and calls it
175
+ */
176
+ void xmlXPathFuncCallback( xmlXPathParserContextPtr ctxt, int nargs) {
177
+ VALUE result, arguments[nargs];
178
+ VALUE ns_hash, func_hash, object;
179
+ const xmlChar *namespace;
180
+ char *rb_func, *chr;
181
+ xmlXPathObjectPtr obj;
182
+ int i;
183
+
184
+ if (ctxt == NULL || ctxt->context == NULL)
185
+ return;
186
+
187
+ rb_func = strdup((char *)ctxt->context->function);
188
+ namespace = ctxt->context->functionURI;
189
+
190
+ ns_hash = rb_cvar_get(cXSLT, rb_intern("@@extFunctions"));
191
+
192
+ func_hash = rb_hash_aref(ns_hash, rb_str_new2((char *)namespace));
193
+
194
+ if(func_hash == Qnil) {
195
+ rb_warning( "xmlXPathFuncCallback: namespace %s not found!\n", namespace );
196
+ }
197
+
198
+ object = rb_hash_aref(func_hash, rb_str_new2((char *)rb_func));
199
+
200
+ for (i = nargs - 1; i >= 0; i--) {
201
+ obj = valuePop(ctxt);
202
+ arguments[i] = xpathObj2value(obj, ctxt->context->doc);
203
+ }
204
+
205
+ /* -s are common in XSLT function names, but illegal for Ruby method names */
206
+ while( (chr = strchr(rb_func, '-')) != NULL ) {
207
+ chr[0] = '_'; /* so we pretend the - was a _ all along */
208
+ }
209
+
210
+ result = rb_funcall2( object, rb_intern(rb_func), nargs, arguments);
211
+
212
+ free( rb_func );
213
+
214
+ obj = value2xpathObj(result);
215
+ valuePush(ctxt, obj);
216
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation; either version 2 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "xslt.h"
20
+
21
+ #include <libxml/xpathInternals.h>
22
+ #include <libxslt/extensions.h>
23
+
24
+ VALUE xpathObj2value( xmlXPathObjectPtr, xmlDocPtr );
25
+ xmlXPathObjectPtr value2xpathObj( VALUE );
26
+ void xmlXPathFuncCallback( xmlXPathParserContextPtr, int );
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation; either version 2 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "xslt.h"
20
+
21
+ /**
22
+ * parameters support, patch from :
23
+ *
24
+ * Eust�quio "TaQ" Rangel
25
+ * eustaquiorangel@yahoo.com
26
+ * http://beam.to/taq
27
+ *
28
+ */
29
+ VALUE each_pair( VALUE obj ) {
30
+ return rb_funcall( obj, rb_intern("each"), 0, 0 );
31
+ }
32
+
33
+ VALUE process_pair( VALUE pair, VALUE rbparams ) {
34
+ VALUE key, value;
35
+ // Thx to alex__
36
+ int count = FIX2INT( rb_funcall( rbparams, rb_intern("size"), 0, 0 ) );
37
+ // static int count = 0;
38
+ char *xValue = NULL;
39
+
40
+ Check_Type( pair, T_ARRAY );
41
+
42
+ key = RARRAY(pair)->ptr[0];
43
+ value = RARRAY(pair)->ptr[1];
44
+
45
+ Check_Type( key, T_STRING );
46
+ Check_Type( value, T_STRING );
47
+
48
+ xValue = STR2CSTR( value );
49
+ if( xValue[0] != '\'' && xValue[strlen( xValue ) - 1] != '\'' ) {
50
+ value = rb_str_concat( value, rb_str_new2( "'" ) );
51
+ value = rb_str_concat( rb_str_new2( "'" ), value );
52
+ }
53
+
54
+ rb_ary_store( rbparams, count, key );
55
+ rb_ary_store( rbparams, count + 1, value );
56
+
57
+ count += 2;
58
+ return Qnil;
59
+ }