libxslt-ruby 0.6.0-x86-mswin32-60 → 0.7.0-x86-mswin32-60

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.
Files changed (42) hide show
  1. data/README +125 -136
  2. data/doc/classes/XSLT.html +215 -0
  3. data/doc/classes/XSLT/Stylesheet.html +244 -0
  4. data/doc/classes/XSLT/TransformContext.html +111 -0
  5. data/doc/created.rid +1 -0
  6. data/doc/files/CHANGES.html +168 -0
  7. data/doc/files/LICENSE.html +133 -0
  8. data/doc/files/README.html +269 -0
  9. data/doc/files/ext/libxslt/libxslt_c.html +101 -0
  10. data/doc/files/ext/libxslt/ruby_xslt_stylesheet_c.html +101 -0
  11. data/doc/files/ext/libxslt/ruby_xslt_transform_context_c.html +101 -0
  12. data/doc/files/lib/deprecated_rb.html +101 -0
  13. data/doc/files/lib/libxslt_rb.html +110 -0
  14. data/doc/fr_class_index.html +29 -0
  15. data/doc/fr_file_index.html +34 -0
  16. data/doc/fr_method_index.html +28 -0
  17. data/doc/index.html +24 -0
  18. data/doc/rdoc-style.css +208 -0
  19. data/ext/libxslt/libxslt.c +21 -212
  20. data/ext/libxslt/libxslt.h +0 -17
  21. data/ext/libxslt/ruby_xslt_stylesheet.c +135 -173
  22. data/ext/libxslt/ruby_xslt_stylesheet.h +5 -10
  23. data/ext/libxslt/ruby_xslt_transform_context.c +5 -2
  24. data/ext/libxslt/version.h +2 -2
  25. data/lib/deprecated.rb +66 -0
  26. data/lib/libxslt.rb +1 -0
  27. data/lib/libxslt_ruby.so +0 -0
  28. data/mingw/libxslt_ruby.so +0 -0
  29. data/tests/files/commentary.dtd +34 -0
  30. data/tests/files/fuzface.xml +154 -0
  31. data/tests/files/fuzface.xsl +4 -0
  32. data/tests/files/params.xml +2 -0
  33. data/tests/files/params.xsl +11 -0
  34. data/tests/files/ramblings.xsl +46 -0
  35. data/tests/test_deprecated.rb +99 -0
  36. data/tests/test_libxslt.rb +21 -0
  37. data/tests/test_stylesheet.rb +64 -0
  38. data/tests/test_suite.rb +3 -0
  39. data/vc/libxslt_ruby.sln +1 -1
  40. data/vc/libxslt_ruby.vcproj +3 -3
  41. metadata +41 -10
  42. data/mingw/mingw.rake +0 -36
@@ -16,11 +16,6 @@
16
16
  #include <libxslt/xsltutils.h>
17
17
  #include <libexslt/exslt.h>
18
18
 
19
- // Includes from libxml-ruby
20
- #include <libxml/ruby_libxml.h>
21
- #include <libxml/ruby_xml_document.h>
22
-
23
-
24
19
  #include "ruby_xslt_stylesheet.h"
25
20
  #include "ruby_xslt_transform_context.h"
26
21
 
@@ -29,21 +24,9 @@
29
24
  #define RUBY_LIBXSLT_SRC_TYPE_NULL 0
30
25
  #define RUBY_LIBXSLT_SRC_TYPE_FILE 1
31
26
 
32
- extern VALUE mXML;
33
- //extern VALUE cXMLDocument;
34
-
35
27
  extern VALUE cXSLT;
36
28
  extern VALUE eXMLXSLTStylesheetRequireParsedDoc;
37
29
 
38
- typedef struct ruby_xslt {
39
- int data_type;
40
- void *data;
41
- VALUE str;
42
- VALUE xml_doc_obj;
43
- VALUE ctxt;
44
- xsltStylesheetPtr xsp;
45
- } ruby_xslt;
46
-
47
30
  #if ((RUBY_LIBXML_VER_MAJ != RUBY_LIBXSLT_VER_MAJ) || (RUBY_LIBXML_VER_MIN != RUBY_LIBXSLT_VER_MIN))
48
31
  #error "Incompatible LibXML-Ruby headers - please install same major/micro version"
49
32
  #endif
@@ -5,79 +5,144 @@
5
5
  #include "libxslt.h"
6
6
  #include "ruby_xslt_stylesheet.h"
7
7
 
8
- VALUE cXSLTStylesheet;
8
+ /*
9
+ * Document-class: XSLT::Stylesheet
10
+ *
11
+ * The XSLT::Stylesheet represents a XSL stylesheet that
12
+ * can be used to transform an XML document. For usage information
13
+ * refer to XSLT::Stylesheet#apply
14
+ *
15
+ */
9
16
 
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_t *rxd;
20
- const char **params;
21
- VALUE parameter, tmp;
22
- int i, len;
23
17
 
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");
18
+ VALUE cXSLTStylesheet;
28
19
 
29
- Data_Get_Struct(xss->xml_doc_obj, ruby_xml_document_t, rxd);
20
+ VALUE
21
+ ruby_xslt_stylesheet_document_klass() {
22
+ VALUE mXML = rb_const_get(rb_cObject, rb_intern("XML"));
23
+ return rb_const_get(mXML, rb_intern("Document"));
24
+ }
30
25
 
31
- params = NULL;
32
26
 
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];
27
+ void
28
+ ruby_xslt_stylesheet_free(xsltStylesheetPtr xstylesheet) {
29
+ xsltFreeStylesheet(xstylesheet);
30
+ }
51
31
 
52
- Check_Type(tmp, T_ARRAY);
53
- Check_Type(RARRAY(tmp)->ptr[0], T_STRING);
54
- Check_Type(RARRAY(tmp)->ptr[1], T_STRING);
32
+ VALUE
33
+ ruby_xslt_stylesheet_alloc(VALUE klass) {
34
+ return Data_Wrap_Struct(cXSLTStylesheet,
35
+ NULL, ruby_xslt_stylesheet_free,
36
+ NULL);
37
+ }
38
+
55
39
 
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
- }
40
+ /* call-seq:
41
+ * XSLT::Stylesheet.new(document) -> XSLT::Stylesheet
42
+ *
43
+ * Creates a new XSLT stylesheet based on the provided document.
44
+ *
45
+ * stylesheet_doc = XML::Document.file('stylesheet_file')
46
+ * stylesheet = XSLT::Stylesheet.new(stylesheet_doc)
47
+ *
48
+ */
49
+ VALUE
50
+ ruby_xslt_stylesheet_initialize(VALUE self, VALUE document) {
51
+ ruby_xml_document_t *rdocument;
52
+
53
+ if (!rb_obj_is_kind_of(document, ruby_xslt_stylesheet_document_klass()))
54
+ rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");
55
+
56
+ Data_Get_Struct(document, ruby_xml_document_t, rdocument);
57
+ DATA_PTR(self) = xsltParseStylesheetDoc(rdocument->doc);
58
+ return self;
59
+ }
64
60
 
65
- break;
66
- default:
67
- rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
61
+ /* Helper method to convert Ruby params to C params */
62
+ char **
63
+ ruby_xslt_coerce_params(VALUE params) {
64
+ char** result;
65
+ size_t length;
66
+ size_t i;
67
+
68
+ length = RARRAY(params)->len;
69
+ result = ALLOC_N(char *, length + 2);
70
+
71
+ for (i=0; i<length; i++) {
72
+ VALUE str = rb_String(RARRAY(params)->ptr[i]);
73
+ int strLen = RSTRING(str)->len;
74
+ result[i] = ALLOC_N(char, strLen + 1);
75
+ memset(result[i], 0, strLen + 1);
76
+ strncpy(result[i], RSTRING(str)->ptr, strLen);
68
77
  }
78
+
79
+ /* Null terminate the array - need to empty elements */
80
+ result[i] = NULL;
81
+ result[i+1] = NULL;
82
+
83
+ return result;
84
+ }
85
+
69
86
 
70
- xss->parsed = ruby_xml_document_wrap(xsltApplyStylesheet(xss->xsp,
71
- rxd->doc, params));
72
-
73
- if (params) {
74
- ruby_xfree(params);
87
+ /* call-seq:
88
+ * stylesheet.apply(document, {params}) -> XML::Document
89
+ *
90
+ * Apply this stylesheet transformation to the provided document.
91
+ * This method may be invoked multiple times.
92
+ *
93
+ * Params:
94
+ *
95
+ * document = An instance of an XML::Document
96
+ * params = An optional hash table that specifies the values
97
+ * for xsl:param values embedded in the stylesheet.
98
+ *
99
+ * Example:
100
+ *
101
+ * stylesheet_doc = XML::Document.file('stylesheet_file')
102
+ * stylesheet = XSLT::Stylesheet.new(stylesheet_doc)
103
+ *
104
+ * xml_doc = XML::Document.file('xml_file')
105
+ * result = stylesheet.apply(xml_doc)
106
+ * result = stylesheet.apply(xml_doc, {:foo => 'bar'})
107
+ */
108
+ VALUE
109
+ ruby_xslt_stylesheet_apply(int argc, VALUE *argv, VALUE self) {
110
+ ruby_xml_document_t *rdocument;
111
+ xsltStylesheetPtr xstylesheet;
112
+ xmlDocPtr result;
113
+ VALUE document;
114
+ VALUE params;
115
+ int i;
116
+
117
+ char** pParams;
118
+
119
+ if (argc > 2 || argc < 1)
120
+ rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
121
+
122
+ document = argv[0];
123
+
124
+ if (!rb_obj_is_kind_of(document, ruby_xslt_stylesheet_document_klass()))
125
+ rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");
126
+
127
+ /* Make sure params is a flat array */
128
+ params = (argc == 2 ? argv[1]: Qnil);
129
+ params = rb_Array(params);
130
+ rb_funcall(params, rb_intern("flatten!"), 0);
131
+ pParams = ruby_xslt_coerce_params(params);
132
+
133
+ Data_Get_Struct(document, ruby_xml_document_t, rdocument);
134
+ Data_Get_Struct(self, xsltStylesheet, xstylesheet);
135
+
136
+ result = xsltApplyStylesheet(xstylesheet, rdocument->doc, pParams);
137
+
138
+ /* Free allocated array of *chars. Note we don't have to
139
+ free the last array item since its set to NULL. */
140
+ for (i=0; i<(RARRAY(params)->len); i++) {
141
+ ruby_xfree(pParams[i]);
75
142
  }
76
-
77
- if (xss->parsed == Qnil)
78
- return(Qfalse);
79
- else
80
- return(Qtrue);
143
+ ruby_xfree(pParams);
144
+
145
+ return ruby_xml_document_wrap(result);
81
146
  }
82
147
 
83
148
 
@@ -90,7 +155,7 @@ ruby_xslt_stylesheet_apply(int argc, VALUE *argv, VALUE self) {
90
155
  * is not the case, a warning is triggered and the method returns
91
156
  * false.
92
157
  */
93
- VALUE
158
+ /*VALUE
94
159
  ruby_xslt_stylesheet_debug(int argc, VALUE *argv, VALUE self) {
95
160
  #ifdef LIBXML_DEBUG_ENABLED
96
161
  OpenFile *fptr;
@@ -130,48 +195,7 @@ ruby_xslt_stylesheet_debug(int argc, VALUE *argv, VALUE self) {
130
195
  return(Qfalse);
131
196
  #endif
132
197
  }
133
-
134
-
135
- void
136
- ruby_xslt_stylesheet_free(ruby_xslt_stylesheet *xss) {
137
- if (xss->xsp != NULL) {
138
- xsltFreeStylesheet(xss->xsp);
139
- xss->xsp = NULL;
140
- }
141
-
142
- ruby_xfree(xss);
143
- }
144
-
145
-
146
- void
147
- ruby_xslt_stylesheet_mark(ruby_xslt_stylesheet *xss) {
148
- if (!NIL_P(xss->parsed)) rb_gc_mark(xss->parsed);
149
- if (!NIL_P(xss->xml_doc_obj)) rb_gc_mark(xss->xml_doc_obj);
150
-
151
- switch (xss->data_type) {
152
- case RUBY_LIBXSLT_SRC_TYPE_FILE:
153
- if (xss->data != NULL)
154
- rb_gc_mark((VALUE)xss->data);
155
- break;
156
- }
157
- }
158
-
159
-
160
- VALUE
161
- ruby_xslt_stylesheet_new(VALUE class, xsltStylesheetPtr xsp) {
162
- ruby_xslt_stylesheet *xss;
163
- VALUE rval;
164
-
165
- rval=Data_Make_Struct(cXSLTStylesheet,ruby_xslt_stylesheet,ruby_xslt_stylesheet_mark,
166
- ruby_xslt_stylesheet_free,xss);
167
- xss->xsp = xsp;
168
- xss->xml_doc_obj = Qnil;
169
- xss->parsed = Qnil;
170
- xss->data_type = RUBY_LIBXSLT_SRC_TYPE_NULL;
171
- xss->data = NULL;
172
-
173
- return rval;
174
- }
198
+ */
175
199
 
176
200
  // TODO should this automatically apply the sheet if not already,
177
201
  // given that we're unlikely to do much else with it?
@@ -183,7 +207,7 @@ ruby_xslt_stylesheet_new(VALUE class, xsltStylesheetPtr xsp) {
183
207
  * stream (an IO instance, defaults to $stdout). You *must* call
184
208
  * +apply+ before this method or an exception will be raised.
185
209
  */
186
- VALUE
210
+ /*VALUE
187
211
  ruby_xslt_stylesheet_print(int argc, VALUE *argv, VALUE self) {
188
212
  OpenFile *fptr;
189
213
  VALUE io;
@@ -219,80 +243,18 @@ ruby_xslt_stylesheet_print(int argc, VALUE *argv, VALUE self) {
219
243
  bytes = xsltSaveResultToFile(out, parsed->doc, xss->xsp);
220
244
 
221
245
  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_t *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_t, 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
- }
246
+ }*/
253
247
 
254
248
 
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_t *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_t, parsed);
276
-
277
- xsltSaveResultToFile(fptr->f, parsed->doc, xss->xsp);
278
-
279
- return(Qtrue);
280
- }
281
-
282
249
  #ifdef RDOC_NEVER_DEFINED
283
- mXML = rb_define_module("XML");
284
- cXSLT = rb_define_class_under(mXML, "XSLT", rb_cObject);
250
+ cXSLT = rb_define_module("XSLT");
251
+ cXSLTStylesheet = rb_define_class_under(cXSLT, "Stylesheet", rb_cObject);
285
252
  #endif
286
253
 
287
254
  void
288
255
  ruby_init_xslt_stylesheet(void) {
289
256
  cXSLTStylesheet = rb_define_class_under(cXSLT, "Stylesheet", rb_cObject);
290
- eXMLXSLTStylesheetRequireParsedDoc =
291
- rb_define_class_under(cXSLTStylesheet, "RequireParsedDoc", rb_eException);
292
-
257
+ rb_define_alloc_func(cXSLTStylesheet, ruby_xslt_stylesheet_alloc);
258
+ rb_define_method(cXSLTStylesheet, "initialize", ruby_xslt_stylesheet_initialize, 1);
293
259
  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
260
  }
@@ -5,17 +5,12 @@
5
5
  #ifndef __RUBY_LIBXSLT_STYLESHEET__
6
6
  #define __RUBY_LIBXSLT_STYLESHEET__
7
7
 
8
- extern VALUE cXSLTStylesheet;
8
+ // Includes from libxml-ruby
9
+ #include <libxml/ruby_libxml.h>
10
+ #include <libxml/ruby_xml_document.h>
9
11
 
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;
12
+ extern VALUE cXSLTStylesheet;
17
13
 
18
14
  void ruby_init_xslt_stylesheet(void);
19
- VALUE ruby_xslt_stylesheet_new(VALUE class, xsltStylesheetPtr xsp);
20
15
 
21
- #endif /* __RUBY_LIBXSLT_STYLESHEET__ */
16
+ #endif
@@ -5,6 +5,9 @@
5
5
  #include "libxslt.h"
6
6
  #include "ruby_xslt_transform_context.h"
7
7
 
8
+
9
+ /* :nodoc: */
10
+
8
11
  VALUE cXSLTTransformContext;
9
12
 
10
13
  void
@@ -50,8 +53,8 @@ ruby_xslt_transform_context_new3(VALUE xslt) {
50
53
  }
51
54
 
52
55
  #ifdef RDOC_NEVER_DEFINED
53
- mXML = rb_define_module("XML");
54
- cXSLT = rb_define_class_under(mXML, "XSLT", rb_cObject);
56
+ cXSLT = rb_define_module("XSLT");
57
+ cXSLTTransformContext = rb_define_class_under(cXSLT, "TransformContext", rb_cObject);
55
58
  #endif
56
59
 
57
60
  void
@@ -1,5 +1,5 @@
1
- #define RUBY_LIBXSLT_VERSION "0.6.0"
1
+ #define RUBY_LIBXSLT_VERSION "0.7.0"
2
2
  #define RUBY_LIBXSLT_VERNUM 0
3
3
  #define RUBY_LIBXSLT_VER_MAJ 0
4
- #define RUBY_LIBXSLT_VER_MIN 6
4
+ #define RUBY_LIBXSLT_VER_MIN 7
5
5
  #define RUBY_LIBXSLT_VER_MIC 0
data/lib/deprecated.rb ADDED
@@ -0,0 +1,66 @@
1
+ # :enddoc:
2
+ # These classes provide provide backwards compatibility with
3
+ # versions of libxslt-ruby prior to version 0.7.0
4
+
5
+ module XML
6
+ module XSLT
7
+ MAX_DEPTH = ::XSLT::MAX_DEPTH
8
+ MAX_SORT = ::XSLT::MAX_SORT
9
+ ENGINE_VERSION = ::XSLT::ENGINE_VERSION
10
+ LIBXSLT_VERSION = ::XSLT::LIBXSLT_VERSION
11
+ LIBXML_VERSION = ::XSLT::LIBXML_VERSION
12
+ XSLT_NAMESPACE = ::XSLT::XSLT_NAMESPACE
13
+ DEFAULT_VENDOR = ::XSLT::DEFAULT_VENDOR
14
+ DEFAULT_VERSION = ::XSLT::DEFAULT_VERSION
15
+ DEFAULT_URL = ::XSLT::DEFAULT_URL
16
+ NAMESPACE_LIBXSLT = ::XSLT::NAMESPACE_LIBXSLT
17
+ NAMESPACE_NORM_SAXON = ::XSLT::NAMESPACE_NORM_SAXON
18
+ NAMESPACE_SAXON = ::XSLT::NAMESPACE_SAXON
19
+ NAMESPACE_XT = ::XSLT::NAMESPACE_XT
20
+ NAMESPACE_XALAN = ::XSLT::NAMESPACE_XALAN
21
+
22
+ def self.new
23
+ Stylesheet.new(nil)
24
+ end
25
+
26
+ def self.file(filename)
27
+ doc = Document.file(filename)
28
+ stylesheet = ::XSLT::Stylesheet.new(doc)
29
+
30
+ result = Stylesheet.new(stylesheet)
31
+ result.filename = filename
32
+ result
33
+ end
34
+
35
+ class Stylesheet
36
+ attr_accessor :doc, :filename
37
+
38
+ def initialize(stylesheet)
39
+ @stylesheet = stylesheet
40
+ end
41
+
42
+ def filename=(value)
43
+ @doc = Document.file(value)
44
+ @filename = value
45
+ end
46
+
47
+ def parse
48
+ self
49
+ end
50
+
51
+ def apply
52
+ @result = @stylesheet.apply(@doc)
53
+ end
54
+
55
+ def save(filename)
56
+ raise(ArgumentError) unless @result
57
+ @result.save(filename)
58
+ end
59
+
60
+ def print(filename)
61
+ raise(ArgumentError) unless @result
62
+ end
63
+ end
64
+ end
65
+ end
66
+