libxsl-ruby 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +14 -0
  2. data/LICENSE +21 -0
  3. data/README +50 -0
  4. data/Rakefile +245 -0
  5. data/TODO +32 -0
  6. data/ext/xml/extconf.rb +97 -0
  7. data/ext/xml/libxml-ruby/libxml.h +92 -0
  8. data/ext/xml/libxml-ruby/ruby_xml_attr.h +31 -0
  9. data/ext/xml/libxml-ruby/ruby_xml_attribute.h +31 -0
  10. data/ext/xml/libxml-ruby/ruby_xml_document.h +37 -0
  11. data/ext/xml/libxml-ruby/ruby_xml_dtd.h +27 -0
  12. data/ext/xml/libxml-ruby/ruby_xml_input_cbg.h +31 -0
  13. data/ext/xml/libxml-ruby/ruby_xml_node.h +38 -0
  14. data/ext/xml/libxml-ruby/ruby_xml_node_set.h +36 -0
  15. data/ext/xml/libxml-ruby/ruby_xml_ns.h +31 -0
  16. data/ext/xml/libxml-ruby/ruby_xml_parser.h +41 -0
  17. data/ext/xml/libxml-ruby/ruby_xml_parser_context.h +32 -0
  18. data/ext/xml/libxml-ruby/ruby_xml_sax_parser.h +31 -0
  19. data/ext/xml/libxml-ruby/ruby_xml_schema.h +26 -0
  20. data/ext/xml/libxml-ruby/ruby_xml_tree.h +22 -0
  21. data/ext/xml/libxml-ruby/ruby_xml_xinclude.h +23 -0
  22. data/ext/xml/libxml-ruby/ruby_xml_xpath.h +34 -0
  23. data/ext/xml/libxml-ruby/ruby_xml_xpath_context.h +34 -0
  24. data/ext/xml/libxml-ruby/ruby_xml_xpointer.h +37 -0
  25. data/ext/xml/libxml-ruby/ruby_xml_xpointer_context.h +28 -0
  26. data/ext/xml/libxslt.c +247 -0
  27. data/ext/xml/libxslt.h +52 -0
  28. data/ext/xml/ruby_xslt_stylesheet.c +298 -0
  29. data/ext/xml/ruby_xslt_stylesheet.h +21 -0
  30. data/ext/xml/ruby_xslt_transform_context.c +63 -0
  31. data/ext/xml/ruby_xslt_transform_context.h +22 -0
  32. data/tests/commentary.dtd +34 -0
  33. data/tests/fuzface.rb +15 -0
  34. data/tests/fuzface.xml +154 -0
  35. data/tests/fuzface.xsl +4 -0
  36. data/tests/ramblings.xsl +46 -0
  37. data/tests/tc_libxslt.rb +65 -0
  38. data/tests/tc_xslt_stylesheet.rb +41 -0
  39. data/tests/tc_xslt_stylesheet2.rb +41 -0
  40. metadata +101 -0
@@ -0,0 +1,52 @@
1
+ /* $Id: libxslt.h,v 1.1 2006/03/24 10:54:55 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __RUBY_LIBXSLT_H__
6
+ #define __RUBY_LIBXSLT_H__
7
+
8
+ #include <ruby.h>
9
+ #include <rubyio.h>
10
+ #include <libxml/parser.h>
11
+ #include <libxml/debugXML.h>
12
+ #include <libxslt/extra.h>
13
+ #include <libxslt/xslt.h>
14
+ #include <libxslt/xsltInternals.h>
15
+ #include <libxslt/transform.h>
16
+ #include <libxslt/xsltutils.h>
17
+ #include <libexslt/exslt.h>
18
+
19
+ #include "libxml-ruby/libxml.h"
20
+ #include "libxml-ruby/ruby_xml_document.h"
21
+ #include "ruby_xslt_stylesheet.h"
22
+ #include "ruby_xslt_transform_context.h"
23
+
24
+ #define RUBY_LIBXSLT_VERSION "0.3.6"
25
+ #define RUBY_LIBXSLT_VERNUM 036
26
+ #define RUBY_LIBXSLT_VER_MAJ 0
27
+ #define RUBY_LIBXSLT_VER_MIN 3
28
+ #define RUBY_LIBXSLT_VER_MIC 6
29
+
30
+ #define RUBY_LIBXSLT_SRC_TYPE_NULL 0
31
+ #define RUBY_LIBXSLT_SRC_TYPE_FILE 1
32
+
33
+ extern VALUE mXML;
34
+ extern VALUE cXMLDocument;
35
+
36
+ extern VALUE cXSLT;
37
+ extern VALUE eXMLXSLTStylesheetRequireParsedDoc;
38
+
39
+ typedef struct ruby_xslt {
40
+ int data_type;
41
+ void *data;
42
+ VALUE str;
43
+ VALUE xml_doc_obj;
44
+ VALUE ctxt;
45
+ xsltStylesheetPtr xsp;
46
+ } ruby_xslt;
47
+
48
+ #if ((RUBY_LIBXML_VER_MAJ != RUBY_LIBXSLT_VER_MAJ) || (RUBY_LIBXML_VER_MIN != RUBY_LIBXSLT_VER_MIN))
49
+ #error "Incompatible LibXML-Ruby headers - please install same major/micro version"
50
+ #endif
51
+
52
+ #endif
@@ -0,0 +1,298 @@
1
+ /* $Id: ruby_xslt_stylesheet.c,v 1.1 2006/03/24 10:54:55 roscopeco Exp $ */
2
+
3
+ /* See the LICENSE file for copyright and distribution information. */
4
+
5
+ #include "libxslt.h"
6
+ #include "ruby_xslt_stylesheet.h"
7
+
8
+ VALUE cXSLTStylesheet;
9
+
10
+ /* call-seq:
11
+ * sheet.apply => (true|false)
12
+ *
13
+ * Apply this stylesheet transformation to the source
14
+ * document.
15
+ */
16
+ VALUE
17
+ ruby_xslt_stylesheet_apply(int argc, VALUE *argv, VALUE self) {
18
+ ruby_xslt_stylesheet *xss;
19
+ ruby_xml_document *rxd;
20
+ const char **params;
21
+ VALUE parameter, tmp;
22
+ int i, len;
23
+
24
+ Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
25
+
26
+ if (NIL_P(xss->xml_doc_obj))
27
+ rb_raise(rb_eArgError, "Need a document object");
28
+
29
+ Data_Get_Struct(xss->xml_doc_obj, ruby_xml_document, rxd);
30
+
31
+ params = NULL;
32
+
33
+ switch(argc) {
34
+ case 0:
35
+ break;
36
+ case 1:
37
+ parameter = argv[0];
38
+ #if RUBY_VERSION_CODE >= 180
39
+ if (TYPE(parameter) == T_HASH) {
40
+ /* Convert parameter to an array */
41
+ parameter = rb_hash_to_a(parameter);
42
+ }
43
+ #endif
44
+
45
+ if (TYPE(parameter) == T_ARRAY) {
46
+ /* A hash is better than an array, but we can live with an array of arrays */
47
+ len = RARRAY(parameter)->len;
48
+ params = (void *)ALLOC_N(char *, (len * 2) + 2);
49
+ for (i=0; i < RARRAY(parameter)->len; i++) {
50
+ tmp = RARRAY(parameter)->ptr[i];
51
+
52
+ Check_Type(tmp, T_ARRAY);
53
+ Check_Type(RARRAY(tmp)->ptr[0], T_STRING);
54
+ Check_Type(RARRAY(tmp)->ptr[1], T_STRING);
55
+
56
+ params[2*i] = RSTRING(RARRAY(tmp)->ptr[0])->ptr;
57
+ params[2*i+1] = RSTRING(RARRAY(tmp)->ptr[1])->ptr;
58
+ }
59
+ params[2*i] = params[2*i+1] = 0;
60
+ } else {
61
+ /* I should test to see if the object responds to to_a and to_h before calling this, but oh well */
62
+ rb_raise(rb_eTypeError, "xslt_stylesheet_appy: expecting a hash or an array of arrays as a parameter");
63
+ }
64
+
65
+ break;
66
+ default:
67
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
68
+ }
69
+
70
+ xss->parsed = ruby_xml_document_new(cXMLDocument,
71
+ xsltApplyStylesheet(xss->xsp,
72
+ rxd->doc, params));
73
+
74
+ if (params) {
75
+ free(params);
76
+ }
77
+
78
+ if (xss->parsed == Qnil)
79
+ return(Qfalse);
80
+ else
81
+ return(Qtrue);
82
+ }
83
+
84
+
85
+ /* call-seq:
86
+ * sheet.debug(to = $stdout) => (true|false)
87
+ *
88
+ * Output a debug dump of this stylesheet to the specified output
89
+ * stream (an instance of IO, defaults to $stdout). Requires
90
+ * libxml/libxslt be compiled with debugging enabled. If this
91
+ * is not the case, a warning is triggered and the method returns
92
+ * false.
93
+ */
94
+ VALUE
95
+ ruby_xslt_stylesheet_debug(int argc, VALUE *argv, VALUE self) {
96
+ #ifdef LIBXML_DEBUG_ENABLED
97
+ OpenFile *fptr;
98
+ VALUE io;
99
+ FILE *out;
100
+ ruby_xml_document *parsed;
101
+ ruby_xslt_stylesheet *xss;
102
+
103
+ Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
104
+ if (NIL_P(xss->parsed))
105
+ rb_raise(eXMLXSLTStylesheetRequireParsedDoc, "must have a parsed XML result");
106
+
107
+ switch (argc) {
108
+ case 0:
109
+ io = rb_stdout;
110
+ break;
111
+ case 1:
112
+ io = argv[0];
113
+ if (rb_obj_is_kind_of(io, rb_cIO) == Qfalse)
114
+ rb_raise(rb_eTypeError, "need an IO object");
115
+ break;
116
+ default:
117
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
118
+ }
119
+
120
+ Data_Get_Struct(xss->parsed, ruby_xml_document, parsed);
121
+ if (parsed->doc == NULL)
122
+ return(Qnil);
123
+
124
+ GetOpenFile(io, fptr);
125
+ rb_io_check_writable(fptr);
126
+ out = GetWriteFile(fptr);
127
+ xmlDebugDumpDocument(out, parsed->doc);
128
+ return(Qtrue);
129
+ #else
130
+ rb_warn("libxml/libxslt was compiled without debugging support. Please recompile libxml/libxslt and their Ruby modules");
131
+ return(Qfalse);
132
+ #endif
133
+ }
134
+
135
+
136
+ void
137
+ ruby_xslt_stylesheet_free(ruby_xslt_stylesheet *xss) {
138
+ if (xss->xsp != NULL) {
139
+ xsltFreeStylesheet(xss->xsp);
140
+ xss->xsp = NULL;
141
+ }
142
+
143
+ free(xss);
144
+ }
145
+
146
+
147
+ void
148
+ ruby_xslt_stylesheet_mark(ruby_xslt_stylesheet *xss) {
149
+ if (!NIL_P(xss->parsed)) rb_gc_mark(xss->parsed);
150
+ if (!NIL_P(xss->xml_doc_obj)) rb_gc_mark(xss->xml_doc_obj);
151
+
152
+ switch (xss->data_type) {
153
+ case RUBY_LIBXSLT_SRC_TYPE_FILE:
154
+ if (xss->data != NULL)
155
+ rb_gc_mark((VALUE)xss->data);
156
+ break;
157
+ }
158
+ }
159
+
160
+
161
+ VALUE
162
+ ruby_xslt_stylesheet_new(VALUE class, xsltStylesheetPtr xsp) {
163
+ ruby_xslt_stylesheet *xss;
164
+
165
+ xss = ALLOC(ruby_xslt_stylesheet);
166
+ xss->xsp = xsp;
167
+ xss->xml_doc_obj = Qnil;
168
+ xss->parsed = Qnil;
169
+ xss->data_type = RUBY_LIBXSLT_SRC_TYPE_NULL;
170
+ xss->data = NULL;
171
+
172
+ return(Data_Wrap_Struct(cXSLTStylesheet, ruby_xslt_stylesheet_mark,
173
+ ruby_xslt_stylesheet_free, xss));
174
+ }
175
+
176
+ // TODO should this automatically apply the sheet if not already,
177
+ // given that we're unlikely to do much else with it?
178
+
179
+ /* call-seq:
180
+ * sheet.print(to = $stdout) => number_of_bytes
181
+ *
182
+ * Output the result of the transform to the specified output
183
+ * stream (an IO instance, defaults to $stdout). You *must* call
184
+ * +apply+ before this method or an exception will be raised.
185
+ */
186
+ VALUE
187
+ ruby_xslt_stylesheet_print(int argc, VALUE *argv, VALUE self) {
188
+ OpenFile *fptr;
189
+ VALUE io;
190
+ FILE *out;
191
+ ruby_xml_document *parsed;
192
+ ruby_xslt_stylesheet *xss;
193
+ int bytes;
194
+
195
+ Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
196
+ if (NIL_P(xss->parsed))
197
+ rb_raise(eXMLXSLTStylesheetRequireParsedDoc, "must have a parsed XML result");
198
+
199
+ switch (argc) {
200
+ case 0:
201
+ io = rb_stdout;
202
+ break;
203
+ case 1:
204
+ io = argv[0];
205
+ if (rb_obj_is_kind_of(io, rb_cIO) == Qfalse)
206
+ rb_raise(rb_eTypeError, "need an IO object");
207
+ break;
208
+ default:
209
+ rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
210
+ }
211
+
212
+ Data_Get_Struct(xss->parsed, ruby_xml_document, parsed);
213
+ if (parsed->doc == NULL)
214
+ return(Qnil);
215
+
216
+ GetOpenFile(io, fptr);
217
+ rb_io_check_writable(fptr);
218
+ out = GetWriteFile(fptr);
219
+ bytes = xsltSaveResultToFile(out, parsed->doc, xss->xsp);
220
+
221
+ return(INT2NUM(bytes));
222
+ }
223
+
224
+ // TODO this, too. Either way, to_s probably should have prereqs
225
+ // like this, for one thing it makes IRB use tricky...
226
+
227
+ /* call-seq:
228
+ * sheet.to_s => "result"
229
+ *
230
+ * Obtain the result of the transform as a string. You *must* call
231
+ * +apply+ before this method or an exception will be raised.
232
+ */
233
+ VALUE
234
+ ruby_xslt_stylesheet_to_s(VALUE self) {
235
+ ruby_xml_document *parsed;
236
+ ruby_xslt_stylesheet *xss;
237
+ xmlChar *str;
238
+ int len;
239
+
240
+ Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
241
+ if (NIL_P(xss->parsed))
242
+ rb_raise(eXMLXSLTStylesheetRequireParsedDoc, "must have a parsed XML result");
243
+ Data_Get_Struct(xss->parsed, ruby_xml_document, parsed);
244
+ if (parsed->doc == NULL)
245
+ return(Qnil);
246
+
247
+ xsltSaveResultToString(&str, &len, parsed->doc, xss->xsp);
248
+ if (str == NULL)
249
+ return(Qnil);
250
+ else
251
+ return(rb_str_new((const char*)str,len));
252
+ }
253
+
254
+
255
+
256
+ /* call-seq:
257
+ * sheet.save(io) => true
258
+ *
259
+ * Save the result of the transform to the supplied open
260
+ * file (an IO instance). You *must* call +apply+ before
261
+ * this method or an exception will be raised.
262
+ */
263
+ VALUE
264
+ ruby_xslt_stylesheet_save(VALUE self, VALUE io) {
265
+ ruby_xml_document *parsed;
266
+ ruby_xslt_stylesheet *xss;
267
+ OpenFile *fptr;
268
+
269
+ if (rb_obj_is_kind_of(io, rb_cIO) == Qfalse)
270
+ rb_raise(rb_eArgError, "Only accept IO objects for saving");
271
+
272
+ GetOpenFile(io, fptr);
273
+
274
+ Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
275
+ Data_Get_Struct(xss->parsed, ruby_xml_document, parsed);
276
+
277
+ xsltSaveResultToFile(fptr->f, parsed->doc, xss->xsp);
278
+
279
+ return(Qtrue);
280
+ }
281
+
282
+ #ifdef RDOC_NEVER_DEFINED
283
+ mXML = rb_define_module("XML");
284
+ cXSLT = rb_define_class_under(mXML, "XSLT", rb_cObject);
285
+ #endif
286
+
287
+ void
288
+ ruby_init_xslt_stylesheet(void) {
289
+ cXSLTStylesheet = rb_define_class_under(cXSLT, "Stylesheet", rb_cObject);
290
+ eXMLXSLTStylesheetRequireParsedDoc =
291
+ rb_define_class_under(cXSLTStylesheet, "RequireParsedDoc", rb_eException);
292
+
293
+ rb_define_method(cXSLTStylesheet, "apply", ruby_xslt_stylesheet_apply, -1);
294
+ rb_define_method(cXSLTStylesheet, "debug", ruby_xslt_stylesheet_debug, -1);
295
+ rb_define_method(cXSLTStylesheet, "print", ruby_xslt_stylesheet_print, -1);
296
+ rb_define_method(cXSLTStylesheet, "to_s", ruby_xslt_stylesheet_to_s, 0);
297
+ rb_define_method(cXSLTStylesheet, "save", ruby_xslt_stylesheet_save, 1);
298
+ }
@@ -0,0 +1,21 @@
1
+ /* $Id: ruby_xslt_stylesheet.h,v 1.1 2006/03/24 10:54:55 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information. */
4
+
5
+ #ifndef __RUBY_LIBXSLT_STYLESHEET__
6
+ #define __RUBY_LIBXSLT_STYLESHEET__
7
+
8
+ extern VALUE cXSLTStylesheet;
9
+
10
+ typedef struct ruby_xslt_stylesheet {
11
+ int data_type;
12
+ void *data;
13
+ VALUE parsed; /* XML::Document # parsed xml document after xsl apply */
14
+ VALUE xml_doc_obj; /* XML::Document */
15
+ xsltStylesheetPtr xsp;
16
+ } ruby_xslt_stylesheet;
17
+
18
+ void ruby_init_xslt_stylesheet(void);
19
+ VALUE ruby_xslt_stylesheet_new(VALUE class, xsltStylesheetPtr xsp);
20
+
21
+ #endif /* __RUBY_LIBXSLT_STYLESHEET__ */
@@ -0,0 +1,63 @@
1
+ /* $Id: ruby_xslt_transform_context.c,v 1.1 2006/03/24 10:54:55 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "libxslt.h"
6
+ #include "ruby_xslt_transform_context.h"
7
+ #include "libxml-ruby/libxml.h"
8
+
9
+ VALUE cXSLTTransformContext;
10
+
11
+ void
12
+ ruby_xslt_transform_context_free(ruby_xslt_transform_context *rxtc) {
13
+ if (rxtc->ctxt != NULL) {
14
+ xsltFreeTransformContext(rxtc->ctxt);
15
+ rxtc->ctxt = NULL;
16
+ }
17
+ free(rxtc);
18
+ }
19
+
20
+ void
21
+ ruby_xslt_transform_context_mark(ruby_xslt_transform_context *rxtc) {
22
+ if (rxtc == NULL) return;
23
+ if (!NIL_P(rxtc->xslt)) rb_gc_mark(rxtc->xslt);
24
+ }
25
+
26
+
27
+ VALUE
28
+ ruby_xslt_transform_context_new(VALUE class, VALUE xslt,
29
+ xsltTransformContextPtr ctxt) {
30
+ ruby_xslt_transform_context *rxtc;
31
+ rxtc = ALLOC(ruby_xslt_transform_context);
32
+ ruby_xml_parser_count++;
33
+ rxtc->ctxt = ctxt;
34
+ rxtc->xslt = xslt;
35
+ //fprintf(stderr,"ruby_xslt_transform_context_new 2\n");
36
+ //if (class == Qfalse)
37
+ //fprintf(stderr,"ruby_xslt_transform_context_new: EEEEK!\n");
38
+ return(Data_Wrap_Struct(class, ruby_xslt_transform_context_mark,
39
+ ruby_xslt_transform_context_free, rxtc));
40
+ }
41
+
42
+
43
+ VALUE
44
+ ruby_xslt_transform_context_new2(VALUE class, VALUE xslt) {
45
+ return(ruby_xslt_transform_context_new(class, xslt, NULL));
46
+ }
47
+
48
+
49
+ VALUE
50
+ ruby_xslt_transform_context_new3(VALUE xslt) {
51
+ return(ruby_xslt_transform_context_new2(cXSLTTransformContext, xslt));
52
+ }
53
+
54
+ #ifdef RDOC_NEVER_DEFINED
55
+ mXML = rb_define_module("XML");
56
+ cXSLT = rb_define_class_under(mXML, "XSLT", rb_cObject);
57
+ #endif
58
+
59
+ void
60
+ ruby_init_xslt_transform_context(void) {
61
+ cXSLTTransformContext =
62
+ rb_define_class_under(cXSLT, "TransformContext", rb_cObject);
63
+ }
@@ -0,0 +1,22 @@
1
+ /* $Id: ruby_xslt_transform_context.h,v 1.1 2006/03/24 10:54:55 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #ifndef __RUBY_XSLT_TRANSFORM_CONTEXT__
6
+ #define __RUBY_XSLT_TRANSFORM_CONTEXT__
7
+
8
+ extern VALUE cXSLTTransformContext;
9
+
10
+ typedef struct ruby_xslt_transform_context {
11
+ xsltTransformContextPtr ctxt;
12
+ VALUE xslt;
13
+ } ruby_xslt_transform_context;
14
+
15
+ void ruby_init_xslt_transform_context(void);
16
+ void ruby_xslt_transform_context_free(ruby_xslt_transform_context *ctxt);
17
+ void ruby_xslt_transform_context_mark(ruby_xslt_transform_context *ctxt);
18
+ VALUE ruby_xslt_transform_context_new(VALUE class, VALUE xslt, xsltTransformContextPtr ctxt);
19
+ VALUE ruby_xslt_transform_context_new2(VALUE class, VALUE xslt);
20
+ VALUE ruby_xslt_transform_context_new3(VALUE xslt);
21
+
22
+ #endif