ox 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ox might be problematic. Click here for more details.
- data/README.rdoc +2 -1
- data/ext/ox/obj_load.c +62 -41
- data/ext/ox/ox.c +46 -25
- data/ext/ox/ox.h +9 -3
- data/ext/ox/parse.c +2 -2
- data/lib/ox.rb +1 -0
- data/lib/ox/bag.rb +88 -0
- data/test/func.rb +13 -2
- metadata +6 -3
data/README.rdoc
CHANGED
@@ -18,7 +18,8 @@ changes with releases making Marshal dumped Object incompatible between some
|
|
18
18
|
versions. The use of a binary format make debugging message streams or file
|
19
19
|
contents next to impossible unless the same version of Ruby and only Ruby is
|
20
20
|
used for inspecting the serialize Object. Ox on the other hand uses human
|
21
|
-
readable XML.
|
21
|
+
readable XML. Ox also includes options that allow strict, tolerant, or a mode
|
22
|
+
that automatically defines missing classes.
|
22
23
|
|
23
24
|
It is possible to write an XML serialization gem with Nokogiri but writing
|
24
25
|
such a package in Ruby results in a module significantly slower than
|
data/ext/ox/obj_load.c
CHANGED
@@ -51,8 +51,9 @@ static VALUE parse_double_time(const char *text, VALUE clas);
|
|
51
51
|
static VALUE parse_regexp(const char *text);
|
52
52
|
|
53
53
|
static VALUE get_var_sym_from_attrs(Attr a);
|
54
|
-
static VALUE get_obj_from_attrs(Attr a,
|
55
|
-
static VALUE get_class_from_attrs(Attr a,
|
54
|
+
static VALUE get_obj_from_attrs(Attr a, PInfo pi);
|
55
|
+
static VALUE get_class_from_attrs(Attr a, PInfo pi);
|
56
|
+
static VALUE classname2class(const char *name, PInfo pi);
|
56
57
|
static unsigned long get_id_from_attrs(PInfo pi, Attr a);
|
57
58
|
static CircArray circ_array_new(void);
|
58
59
|
static void circ_array_free(CircArray ca);
|
@@ -93,48 +94,37 @@ name2var(const char *name) {
|
|
93
94
|
}
|
94
95
|
|
95
96
|
inline static VALUE
|
96
|
-
|
97
|
-
VALUE *slot;
|
97
|
+
resolve_classname(VALUE mod, const char *class_name, Effort effort) {
|
98
98
|
VALUE clas;
|
99
|
-
|
100
|
-
if (Qundef == (clas = ox_cache_get(class_cache, name, &slot))) {
|
101
|
-
char class_name[1024];
|
102
|
-
char *s;
|
103
|
-
const char *n = name;
|
104
|
-
ID ci;
|
99
|
+
ID ci = rb_intern(class_name);
|
105
100
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
if (!best_effort || rb_const_defined(clas, ci)) {
|
113
|
-
clas = rb_const_get(clas, ci);
|
114
|
-
} else {
|
115
|
-
return Qundef;
|
116
|
-
}
|
117
|
-
s = class_name;
|
118
|
-
} else {
|
119
|
-
*s++ = *n;
|
120
|
-
}
|
101
|
+
switch (effort) {
|
102
|
+
case TolerantEffort:
|
103
|
+
if (rb_const_defined(mod, ci)) {
|
104
|
+
clas = rb_const_get(mod, ci);
|
105
|
+
} else {
|
106
|
+
clas = Qundef;
|
121
107
|
}
|
122
|
-
|
123
|
-
|
124
|
-
if (
|
125
|
-
clas = rb_const_get(
|
108
|
+
break;
|
109
|
+
case AutoEffort:
|
110
|
+
if (rb_const_defined(mod, ci)) {
|
111
|
+
clas = rb_const_get(mod, ci);
|
126
112
|
} else {
|
127
|
-
|
113
|
+
clas = rb_define_class_under(mod, class_name, ox_bag_clas);
|
128
114
|
}
|
129
|
-
|
130
|
-
|
115
|
+
break;
|
116
|
+
case StrictEffort:
|
117
|
+
default:
|
118
|
+
// raise an error if name is not defined
|
119
|
+
clas = rb_const_get(mod, ci);
|
120
|
+
break;
|
131
121
|
}
|
132
122
|
return clas;
|
133
123
|
}
|
134
124
|
|
135
125
|
inline static VALUE
|
136
|
-
classname2obj(const char *name,
|
137
|
-
VALUE clas = classname2class(name,
|
126
|
+
classname2obj(const char *name, PInfo pi) {
|
127
|
+
VALUE clas = classname2class(name, pi);
|
138
128
|
|
139
129
|
if (Qundef == clas) {
|
140
130
|
return Qnil;
|
@@ -178,6 +168,37 @@ parse_time(const char *text, VALUE clas) {
|
|
178
168
|
return t;
|
179
169
|
}
|
180
170
|
|
171
|
+
static VALUE
|
172
|
+
classname2class(const char *name, PInfo pi) {
|
173
|
+
VALUE *slot;
|
174
|
+
VALUE clas;
|
175
|
+
|
176
|
+
if (Qundef == (clas = ox_cache_get(class_cache, name, &slot))) {
|
177
|
+
char class_name[1024];
|
178
|
+
char *s;
|
179
|
+
const char *n = name;
|
180
|
+
|
181
|
+
clas = rb_cObject;
|
182
|
+
for (s = class_name; '\0' != *n; n++) {
|
183
|
+
if (':' == *n) {
|
184
|
+
*s = '\0';
|
185
|
+
n++;
|
186
|
+
if (Qundef == (clas = resolve_classname(clas, class_name, pi->effort))) {
|
187
|
+
return Qundef;
|
188
|
+
}
|
189
|
+
s = class_name;
|
190
|
+
} else {
|
191
|
+
*s++ = *n;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
*s = '\0';
|
195
|
+
if (Qundef != (clas = resolve_classname(clas, class_name, pi->effort))) {
|
196
|
+
*slot = clas;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
return clas;
|
200
|
+
}
|
201
|
+
|
181
202
|
static VALUE
|
182
203
|
get_var_sym_from_attrs(Attr a) {
|
183
204
|
for (; 0 != a->name; a++) {
|
@@ -189,10 +210,10 @@ get_var_sym_from_attrs(Attr a) {
|
|
189
210
|
}
|
190
211
|
|
191
212
|
static VALUE
|
192
|
-
get_obj_from_attrs(Attr a,
|
213
|
+
get_obj_from_attrs(Attr a, PInfo pi) {
|
193
214
|
for (; 0 != a->name; a++) {
|
194
215
|
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
195
|
-
return classname2obj(a->value,
|
216
|
+
return classname2obj(a->value, pi);
|
196
217
|
}
|
197
218
|
}
|
198
219
|
return Qundef;
|
@@ -209,10 +230,10 @@ get_struct_from_attrs(Attr a) {
|
|
209
230
|
}
|
210
231
|
|
211
232
|
static VALUE
|
212
|
-
get_class_from_attrs(Attr a,
|
233
|
+
get_class_from_attrs(Attr a, PInfo pi) {
|
213
234
|
for (; 0 != a->name; a++) {
|
214
235
|
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
215
|
-
return classname2class(a->value,
|
236
|
+
return classname2class(a->value, pi);
|
216
237
|
}
|
217
238
|
}
|
218
239
|
return Qundef;
|
@@ -537,7 +558,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
537
558
|
break;
|
538
559
|
case RawCode:
|
539
560
|
if (hasChildren) {
|
540
|
-
h->obj = parse(pi->s, ox_gen_callbacks, &pi->s, pi->trace, pi->
|
561
|
+
h->obj = parse(pi->s, ox_gen_callbacks, &pi->s, pi->trace, pi->effort);
|
541
562
|
if (0 != pi->circ_array) {
|
542
563
|
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
543
564
|
}
|
@@ -546,7 +567,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
546
567
|
}
|
547
568
|
break;
|
548
569
|
case ObjectCode:
|
549
|
-
h->obj = get_obj_from_attrs(attrs, pi
|
570
|
+
h->obj = get_obj_from_attrs(attrs, pi);
|
550
571
|
if (0 != pi->circ_array && Qnil != h->obj) {
|
551
572
|
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
552
573
|
}
|
@@ -558,7 +579,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
558
579
|
}
|
559
580
|
break;
|
560
581
|
case ClassCode:
|
561
|
-
h->obj = get_class_from_attrs(attrs, pi
|
582
|
+
h->obj = get_class_from_attrs(attrs, pi);
|
562
583
|
break;
|
563
584
|
case RefCode:
|
564
585
|
h->obj = Qundef;
|
data/ext/ox/ox.c
CHANGED
@@ -71,7 +71,10 @@ VALUE optimized_sym;
|
|
71
71
|
VALUE object_sym;
|
72
72
|
VALUE generic_sym;
|
73
73
|
VALUE limited_sym;
|
74
|
-
VALUE
|
74
|
+
VALUE strict_sym;
|
75
|
+
VALUE tolerant_sym;
|
76
|
+
VALUE effort_sym;
|
77
|
+
VALUE auto_define_sym;
|
75
78
|
VALUE trace_sym;
|
76
79
|
VALUE empty_string;
|
77
80
|
VALUE zero_fixnum;
|
@@ -81,7 +84,7 @@ VALUE ox_comment_clas;
|
|
81
84
|
VALUE ox_doctype_clas;
|
82
85
|
VALUE ox_document_clas;
|
83
86
|
VALUE ox_element_clas;
|
84
|
-
VALUE
|
87
|
+
VALUE ox_bag_clas;
|
85
88
|
VALUE struct_class;
|
86
89
|
VALUE time_class;
|
87
90
|
|
@@ -112,7 +115,7 @@ to_obj(VALUE self, VALUE ruby_xml) {
|
|
112
115
|
Check_Type(ruby_xml, T_STRING);
|
113
116
|
// the xml string gets modified so make a copy of it
|
114
117
|
xml = strdup(StringValuePtr(ruby_xml));
|
115
|
-
obj = parse(xml, ox_obj_callbacks, 0, 0,
|
118
|
+
obj = parse(xml, ox_obj_callbacks, 0, 0, StrictEffort);
|
116
119
|
free(xml);
|
117
120
|
return obj;
|
118
121
|
}
|
@@ -131,7 +134,7 @@ to_gen(VALUE self, VALUE ruby_xml) {
|
|
131
134
|
Check_Type(ruby_xml, T_STRING);
|
132
135
|
// the xml string gets modified so make a copy of it
|
133
136
|
xml = strdup(StringValuePtr(ruby_xml));
|
134
|
-
obj = parse(xml, ox_gen_callbacks, 0, 0,
|
137
|
+
obj = parse(xml, ox_gen_callbacks, 0, 0, StrictEffort);
|
135
138
|
free(xml);
|
136
139
|
return obj;
|
137
140
|
}
|
@@ -147,8 +150,8 @@ static VALUE
|
|
147
150
|
load(char *xml, int argc, VALUE *argv, VALUE self) {
|
148
151
|
VALUE obj;
|
149
152
|
int mode = AutoMode;
|
153
|
+
int effort = StrictEffort;
|
150
154
|
int trace = 0;
|
151
|
-
int best_effort = 0;
|
152
155
|
|
153
156
|
if (1 == argc && rb_cHash == rb_obj_class(*argv)) {
|
154
157
|
VALUE h = *argv;
|
@@ -169,27 +172,35 @@ load(char *xml, int argc, VALUE *argv, VALUE self) {
|
|
169
172
|
rb_raise(rb_eArgError, ":mode must be :generic, :object, or :limited.\n");
|
170
173
|
}
|
171
174
|
}
|
175
|
+
if (Qnil != (v = rb_hash_lookup(h, effort_sym))) {
|
176
|
+
if (auto_define_sym == v) {
|
177
|
+
effort = AutoEffort;
|
178
|
+
} else if (tolerant_sym == v) {
|
179
|
+
effort = TolerantEffort;
|
180
|
+
} else if (strict_sym == v) {
|
181
|
+
effort = StrictEffort;
|
182
|
+
} else {
|
183
|
+
rb_raise(rb_eArgError, ":effort must be :strict, :tolerant, or :auto_define.\n");
|
184
|
+
}
|
185
|
+
}
|
172
186
|
if (Qnil != (v = rb_hash_lookup(h, trace_sym))) {
|
173
187
|
Check_Type(v, T_FIXNUM);
|
174
188
|
trace = FIX2INT(v);
|
175
189
|
}
|
176
|
-
if (Qnil != (v = rb_hash_lookup(h, best_effort_sym))) {
|
177
|
-
best_effort = (Qfalse != v);
|
178
|
-
}
|
179
190
|
}
|
180
191
|
switch (mode) {
|
181
192
|
case ObjMode:
|
182
|
-
obj = parse(xml, ox_obj_callbacks, 0, trace,
|
193
|
+
obj = parse(xml, ox_obj_callbacks, 0, trace, effort);
|
183
194
|
break;
|
184
195
|
case GenMode:
|
185
|
-
obj = parse(xml, ox_gen_callbacks, 0, trace,
|
196
|
+
obj = parse(xml, ox_gen_callbacks, 0, trace, StrictEffort);
|
186
197
|
break;
|
187
198
|
case LimMode:
|
188
|
-
obj = parse(xml, ox_limited_callbacks, 0, trace,
|
199
|
+
obj = parse(xml, ox_limited_callbacks, 0, trace, effort);
|
189
200
|
break;
|
190
201
|
case AutoMode:
|
191
202
|
default:
|
192
|
-
obj = parse(xml, ox_gen_callbacks, 0, trace,
|
203
|
+
obj = parse(xml, ox_gen_callbacks, 0, trace, StrictEffort);
|
193
204
|
break;
|
194
205
|
}
|
195
206
|
free(xml);
|
@@ -204,12 +215,15 @@ load(char *xml, int argc, VALUE *argv, VALUE self) {
|
|
204
215
|
* malformed or the classes specified are not valid.
|
205
216
|
* [xml] XML String
|
206
217
|
* [options] load options
|
207
|
-
* [:mode]
|
208
|
-
*
|
209
|
-
*
|
210
|
-
*
|
211
|
-
* [:
|
212
|
-
*
|
218
|
+
* [:mode] format expected
|
219
|
+
* [:object] object format
|
220
|
+
* [:generic] read as a generic XML file
|
221
|
+
* [:limited] read as a generic XML file but with callbacks on text and elements events only
|
222
|
+
* [:effort] effort to use when an undefined class is encountered, default: :strict
|
223
|
+
* [:strict] raise an NameError for missing classes and modules
|
224
|
+
* [:tolerant] return nil for missing classes and modules
|
225
|
+
* [:auto_define] auto define missing classes and modules
|
226
|
+
* [:trace] trace level as a Fixnum, default: 0 (silent)
|
213
227
|
*/
|
214
228
|
static VALUE
|
215
229
|
load_str(int argc, VALUE *argv, VALUE self) {
|
@@ -229,12 +243,15 @@ load_str(int argc, VALUE *argv, VALUE self) {
|
|
229
243
|
* malformed or the classes specified are not valid.
|
230
244
|
* [file_path] file path to read the XML document from
|
231
245
|
* [options] load options
|
232
|
-
* [:mode]
|
233
|
-
*
|
234
|
-
*
|
235
|
-
*
|
236
|
-
* [:
|
237
|
-
*
|
246
|
+
* [:mode] format expected
|
247
|
+
* [:object] object format
|
248
|
+
* [:generic] read as a generic XML file
|
249
|
+
* [:limited] read as a generic XML file but with callbacks on text and elements events only
|
250
|
+
* [:effort] effort to use when an undefined class is encountered, default: :strict
|
251
|
+
* [:strict] raise an NameError for missing classes and modules
|
252
|
+
* [:tolerant] return nil for missing classes and modules
|
253
|
+
* [:auto_define] auto define missing classes and modules
|
254
|
+
* [:trace] trace level as a Fixnum, default: 0 (silent)
|
238
255
|
*/
|
239
256
|
static VALUE
|
240
257
|
load_file(int argc, VALUE *argv, VALUE self) {
|
@@ -419,7 +436,10 @@ void Init_ox() {
|
|
419
436
|
generic_sym = ID2SYM(rb_intern("generic"));
|
420
437
|
limited_sym = ID2SYM(rb_intern("limited"));
|
421
438
|
trace_sym = ID2SYM(rb_intern("trace"));
|
422
|
-
|
439
|
+
effort_sym = ID2SYM(rb_intern("effort"));
|
440
|
+
strict_sym = ID2SYM(rb_intern("strict"));
|
441
|
+
tolerant_sym = ID2SYM(rb_intern("tolerant"));
|
442
|
+
auto_define_sym = ID2SYM(rb_intern("auto_define"));
|
423
443
|
empty_string = rb_str_new2("");
|
424
444
|
zero_fixnum = INT2NUM(0);
|
425
445
|
|
@@ -429,6 +449,7 @@ void Init_ox() {
|
|
429
449
|
ox_comment_clas = rb_const_get(Ox, rb_intern("Comment"));
|
430
450
|
ox_doctype_clas = rb_const_get(Ox, rb_intern("DocType"));
|
431
451
|
ox_cdata_clas = rb_const_get(Ox, rb_intern("CData"));
|
452
|
+
ox_bag_clas = rb_const_get(Ox, rb_intern("Bag"));
|
432
453
|
|
433
454
|
ox_cache_new(&symbol_cache);
|
434
455
|
ox_cache_new(&class_cache);
|
data/ext/ox/ox.h
CHANGED
@@ -65,6 +65,12 @@ typedef enum {
|
|
65
65
|
UseRaw = 11,
|
66
66
|
} Use;
|
67
67
|
|
68
|
+
typedef enum {
|
69
|
+
StrictEffort = 0,
|
70
|
+
TolerantEffort = 1,
|
71
|
+
AutoEffort = 2,
|
72
|
+
} Effort;
|
73
|
+
|
68
74
|
typedef enum {
|
69
75
|
NoCode = 0,
|
70
76
|
ArrayCode = 'a',
|
@@ -133,10 +139,10 @@ struct _PInfo {
|
|
133
139
|
rb_encoding *encoding;
|
134
140
|
unsigned long id; /* set for text types when cirs_array is set */
|
135
141
|
int trace;
|
136
|
-
|
142
|
+
Effort effort;
|
137
143
|
};
|
138
144
|
|
139
|
-
extern VALUE parse(char *xml, ParseCallbacks pcb, char **endp, int trace,
|
145
|
+
extern VALUE parse(char *xml, ParseCallbacks pcb, char **endp, int trace, Effort effort);
|
140
146
|
extern void _raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
|
141
147
|
|
142
148
|
extern char* write_obj_to_str(VALUE obj, int indent, int xsd_date, int circular);
|
@@ -172,7 +178,7 @@ extern VALUE zero_fixnum;
|
|
172
178
|
|
173
179
|
extern VALUE ox_document_clas;
|
174
180
|
extern VALUE ox_element_clas;
|
175
|
-
extern VALUE
|
181
|
+
extern VALUE ox_bag_clas;
|
176
182
|
extern VALUE ox_comment_clas;
|
177
183
|
extern VALUE ox_doctype_clas;
|
178
184
|
extern VALUE ox_cdata_clas;
|
data/ext/ox/parse.c
CHANGED
@@ -79,7 +79,7 @@ next_non_white(PInfo pi) {
|
|
79
79
|
}
|
80
80
|
|
81
81
|
VALUE
|
82
|
-
parse(char *xml, ParseCallbacks pcb, char **endp, int trace,
|
82
|
+
parse(char *xml, ParseCallbacks pcb, char **endp, int trace, Effort effort) {
|
83
83
|
struct _PInfo pi;
|
84
84
|
int body_read = 0;
|
85
85
|
|
@@ -98,7 +98,7 @@ parse(char *xml, ParseCallbacks pcb, char **endp, int trace, int best_effort) {
|
|
98
98
|
pi.circ_array = 0;
|
99
99
|
pi.encoding = 0;
|
100
100
|
pi.trace = trace;
|
101
|
-
pi.
|
101
|
+
pi.effort = effort;
|
102
102
|
while (1) {
|
103
103
|
next_non_white(&pi); // skip white space
|
104
104
|
if ('\0' == *pi.s) {
|
data/lib/ox.rb
CHANGED
data/lib/ox/bag.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
module Ox
|
3
|
+
|
4
|
+
# A generic class that is used only for storing attributes. It is the base
|
5
|
+
# Class for auto-generated classes in the storage system. Instance variables
|
6
|
+
# are added using the instance_variable_set() method. All instance variables
|
7
|
+
# can be accessed using the variable name (without the @ prefix). No setters
|
8
|
+
# are provided as the Class is intended for reading only.
|
9
|
+
class Bag
|
10
|
+
|
11
|
+
# The initializer can take multiple arguments in the form of key values
|
12
|
+
# where the key is the variable name and the value is the variable
|
13
|
+
# value. This is intended for testing purposes only.
|
14
|
+
# Example: Ox::Bag.new(:@x => 42, :@y => 57)
|
15
|
+
def initialize(args={ })
|
16
|
+
args.each do |k,v|
|
17
|
+
self.instance_variable_set(k, v)
|
18
|
+
m = k.to_s[1..-1].to_sym
|
19
|
+
unless respond_to?(m)
|
20
|
+
self.class.define_get(m, k)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Replaces the Object.respond_to?() method to return true for any method
|
26
|
+
# than matches instance variables.
|
27
|
+
# [m] method symbol
|
28
|
+
def respond_to?(m)
|
29
|
+
at_m = ('@' + m.to_s).to_sym
|
30
|
+
instance_variables.include?(at_m)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Handles requests for variable values. Others cause an Exception to be
|
34
|
+
# raised.
|
35
|
+
# [m] method symbol
|
36
|
+
def method_missing(m, *args, &block)
|
37
|
+
raise ArgumentError.new("wrong number of arguments(#{args.size} for 0)") unless args.nil? or args.empty?
|
38
|
+
at_m = ('@' + m.to_s).to_sym
|
39
|
+
raise NoMethodError("undefined method", m) unless instance_variable_defined?(at_m)
|
40
|
+
instance_variable_get(at_m)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Replace eql?() with something more reasonable for this Class.
|
44
|
+
# [other] Object to compare this one to
|
45
|
+
def eql?(other)
|
46
|
+
return false if (other.nil? or self.class != other.class)
|
47
|
+
ova = other.instance_variables
|
48
|
+
iv = instance_variables
|
49
|
+
return false if ova.size != iv.size
|
50
|
+
iv.each do |vid|
|
51
|
+
return false if instance_variable_get(vid) != other.instance_variable_get(vid)
|
52
|
+
end
|
53
|
+
true
|
54
|
+
end
|
55
|
+
alias == eql?
|
56
|
+
|
57
|
+
end # Bag
|
58
|
+
|
59
|
+
# Define a new class based on the Ox::Bag class. This is used internally in
|
60
|
+
# the Ox module and is available to service wrappers that receive XML
|
61
|
+
# requests that include Objects of Classes not defined in the storage
|
62
|
+
# process.
|
63
|
+
# [classname] Class name or symbol that includes Module names
|
64
|
+
def self.define_class(classname)
|
65
|
+
classname = classname.to_s unless classname.is_a?(String)
|
66
|
+
tokens = classname.split('::').map { |n| n.to_sym }
|
67
|
+
raise "Invalid classname '#{classname}" if tokens.empty?
|
68
|
+
m = Object
|
69
|
+
tokens[0..-2].each do |sym|
|
70
|
+
if m.const_defined?(sym)
|
71
|
+
m = m.const_get(sym)
|
72
|
+
else
|
73
|
+
c = Module.new
|
74
|
+
m.const_set(sym, c)
|
75
|
+
m = c
|
76
|
+
end
|
77
|
+
end
|
78
|
+
sym = tokens[-1]
|
79
|
+
if m.const_defined?(sym)
|
80
|
+
c = m.const_get(sym)
|
81
|
+
else
|
82
|
+
c = Class.new(Ox::Bag)
|
83
|
+
m.const_set(sym, c)
|
84
|
+
end
|
85
|
+
c
|
86
|
+
end
|
87
|
+
|
88
|
+
end # Ox
|
data/test/func.rb
CHANGED
@@ -112,15 +112,26 @@ class Func < ::Test::Unit::TestCase
|
|
112
112
|
|
113
113
|
def test_bad_object
|
114
114
|
xml = %{<?xml version="1.0"?>
|
115
|
-
<o c="Bad">
|
115
|
+
<o c="Bad::Boy">
|
116
116
|
<i a="@x">3</i>
|
117
117
|
</o>
|
118
|
+
}
|
119
|
+
xml2 = %{<?xml version="1.0"?>
|
120
|
+
<o c="Bad">
|
121
|
+
<i a="@x">7</i>
|
122
|
+
</o>
|
118
123
|
}
|
119
124
|
assert_raise(NameError) {
|
120
125
|
Ox.load(xml, :mode => :object, :trace => 0)
|
121
126
|
}
|
122
|
-
loaded = Ox.load(xml, :mode => :object, :trace => 0, :
|
127
|
+
loaded = Ox.load(xml, :mode => :object, :trace => 0, :effort => :tolerant)
|
123
128
|
assert_equal(loaded, nil)
|
129
|
+
loaded = Ox.load(xml, :mode => :object, :trace => 0, :effort => :auto_define)
|
130
|
+
assert_equal(loaded.class.to_s, 'Bad::Boy')
|
131
|
+
assert_equal(loaded.class.superclass.to_s, 'Ox::Bag')
|
132
|
+
loaded = Ox.load(xml2, :mode => :object, :trace => 0, :effort => :auto_define)
|
133
|
+
assert_equal(loaded.class.to_s, 'Bad')
|
134
|
+
assert_equal(loaded.class.superclass.to_s, 'Ox::Bag')
|
124
135
|
end
|
125
136
|
|
126
137
|
def test_class
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.0
|
5
|
+
version: 1.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Peter Ohler
|
@@ -10,7 +10,8 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-07-
|
13
|
+
date: 2011-07-06 00:00:00 +09:00
|
14
|
+
default_executable:
|
14
15
|
dependencies: []
|
15
16
|
|
16
17
|
description: A fast XML parser and object serializer that uses only standard C lib.
|
@@ -22,6 +23,7 @@ extensions:
|
|
22
23
|
extra_rdoc_files:
|
23
24
|
- README.rdoc
|
24
25
|
files:
|
26
|
+
- lib/ox/bag.rb
|
25
27
|
- lib/ox/cdata.rb
|
26
28
|
- lib/ox/comment.rb
|
27
29
|
- lib/ox/doctype.rb
|
@@ -73,6 +75,7 @@ files:
|
|
73
75
|
- test/Sample.graffle
|
74
76
|
- LICENSE
|
75
77
|
- README.rdoc
|
78
|
+
has_rdoc: true
|
76
79
|
homepage: http://www.ohler.com/ox
|
77
80
|
licenses: []
|
78
81
|
|
@@ -98,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
101
|
requirements: []
|
99
102
|
|
100
103
|
rubyforge_project: ox
|
101
|
-
rubygems_version: 1.
|
104
|
+
rubygems_version: 1.6.2
|
102
105
|
signing_key:
|
103
106
|
specification_version: 3
|
104
107
|
summary: A fast XML parser and object serializer.
|