ox 2.14.16 → 2.14.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/ext/ox/builder.c +3 -37
- data/ext/ox/dump.c +9 -58
- data/ext/ox/extconf.rb +0 -5
- data/ext/ox/gen_load.c +1 -3
- data/ext/ox/obj_load.c +2 -24
- data/ext/ox/ox.c +91 -130
- data/ext/ox/ox.h +0 -5
- data/ext/ox/sax.c +18 -8
- data/ext/ox/sax_as.c +0 -8
- data/ext/ox/slotcache.c +1 -1
- data/lib/ox/version.rb +1 -1
- data/lib/ox/xmlrpc_adapter.rb +1 -0
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b849217680d29abfe528da7bd89f0d5b2700f19a28dd09ed176a663f4cd35ab
|
4
|
+
data.tar.gz: 1a4690fc380ca55710b5ddf1d862503a1e6ef7cdfa9a5ebfb973c9c5b4ed6ea4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98b13052c1015400d8bbec0f79525562eb6e47e21826ca7c89b9197096ead85701211139be6562e5a72d411a47f75d0bb8c354b9ccc28e9c9eaf05ac897dc8ce
|
7
|
+
data.tar.gz: 94ea365ef3cd0a40e36d743b15b0d587748f0d26df8fcb1a9d660c431c6179011fc3531dc559bea95ea5f5b3594907b17f5f1369c0ac5f660ad657f21c286a04
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
All changes to the Ox gem are documented here. Releases follow semantic versioning.
|
4
4
|
|
5
|
+
## [2.14.17] - 2023-07-14
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
|
9
|
+
- The sax parser in html mode now allows unquoted attribute values with complaints.
|
10
|
+
|
5
11
|
## [2.14.16] - 2023-04-11
|
6
12
|
|
7
13
|
### Fixed
|
data/ext/ox/builder.c
CHANGED
@@ -337,21 +337,13 @@ static VALUE builder_new(int argc, VALUE *argv, VALUE self) {
|
|
337
337
|
|
338
338
|
rb_check_type(*argv, T_HASH);
|
339
339
|
if (Qnil != (v = rb_hash_lookup(*argv, ox_indent_sym))) {
|
340
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
341
340
|
if (rb_cInteger != rb_obj_class(v)) {
|
342
|
-
#else
|
343
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
344
|
-
#endif
|
345
341
|
rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
|
346
342
|
}
|
347
343
|
indent = NUM2INT(v);
|
348
344
|
}
|
349
345
|
if (Qnil != (v = rb_hash_lookup(*argv, ox_size_sym))) {
|
350
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
351
346
|
if (rb_cInteger != rb_obj_class(v)) {
|
352
|
-
#else
|
353
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
354
|
-
#endif
|
355
347
|
rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
|
356
348
|
}
|
357
349
|
buf_size = NUM2LONG(v);
|
@@ -400,21 +392,13 @@ static VALUE builder_file(int argc, VALUE *argv, VALUE self) {
|
|
400
392
|
|
401
393
|
rb_check_type(argv[1], T_HASH);
|
402
394
|
if (Qnil != (v = rb_hash_lookup(argv[1], ox_indent_sym))) {
|
403
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
404
395
|
if (rb_cInteger != rb_obj_class(v)) {
|
405
|
-
#else
|
406
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
407
|
-
#endif
|
408
396
|
rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
|
409
397
|
}
|
410
398
|
indent = NUM2INT(v);
|
411
399
|
}
|
412
400
|
if (Qnil != (v = rb_hash_lookup(argv[1], ox_size_sym))) {
|
413
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
414
401
|
if (rb_cInteger != rb_obj_class(v)) {
|
415
|
-
#else
|
416
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
417
|
-
#endif
|
418
402
|
rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
|
419
403
|
}
|
420
404
|
buf_size = NUM2LONG(v);
|
@@ -461,21 +445,13 @@ static VALUE builder_io(int argc, VALUE *argv, VALUE self) {
|
|
461
445
|
|
462
446
|
rb_check_type(argv[1], T_HASH);
|
463
447
|
if (Qnil != (v = rb_hash_lookup(argv[1], ox_indent_sym))) {
|
464
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
465
448
|
if (rb_cInteger != rb_obj_class(v)) {
|
466
|
-
#else
|
467
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
468
|
-
#endif
|
469
449
|
rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
|
470
450
|
}
|
471
451
|
indent = NUM2INT(v);
|
472
452
|
}
|
473
453
|
if (Qnil != (v = rb_hash_lookup(argv[1], ox_size_sym))) {
|
474
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
475
454
|
if (rb_cInteger != rb_obj_class(v)) {
|
476
|
-
#else
|
477
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
478
|
-
#endif
|
479
455
|
rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
|
480
456
|
}
|
481
457
|
buf_size = NUM2LONG(v);
|
@@ -732,9 +708,7 @@ static VALUE builder_text(int argc, VALUE *argv, VALUE self) {
|
|
732
708
|
strip_invalid_chars = Qfalse;
|
733
709
|
}
|
734
710
|
|
735
|
-
|
736
|
-
v = rb_funcall(v, ox_to_s_id, 0);
|
737
|
-
}
|
711
|
+
v = rb_String(v);
|
738
712
|
i_am_a_child(b, true);
|
739
713
|
append_string(b, StringValuePtr(v), RSTRING_LEN(v), xml_element_chars, RTEST(strip_invalid_chars));
|
740
714
|
|
@@ -754,9 +728,7 @@ static VALUE builder_cdata(VALUE self, VALUE data) {
|
|
754
728
|
const char *end;
|
755
729
|
int len;
|
756
730
|
|
757
|
-
|
758
|
-
v = rb_funcall(v, ox_to_s_id, 0);
|
759
|
-
}
|
731
|
+
v = rb_String(v);
|
760
732
|
str = StringValuePtr(v);
|
761
733
|
len = (int)RSTRING_LEN(v);
|
762
734
|
s = str;
|
@@ -796,9 +768,7 @@ static VALUE builder_raw(VALUE self, VALUE text) {
|
|
796
768
|
const char *end;
|
797
769
|
int len;
|
798
770
|
|
799
|
-
|
800
|
-
v = rb_funcall(v, ox_to_s_id, 0);
|
801
|
-
}
|
771
|
+
v = rb_String(v);
|
802
772
|
str = StringValuePtr(v);
|
803
773
|
len = (int)RSTRING_LEN(v);
|
804
774
|
s = str;
|
@@ -857,11 +827,7 @@ static VALUE builder_get_indent(VALUE self) {
|
|
857
827
|
* - +indent+ (Fixnum) indentaion level, negative values excludes terminating newline
|
858
828
|
*/
|
859
829
|
static VALUE builder_set_indent(VALUE self, VALUE indent) {
|
860
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
861
830
|
if (rb_cInteger != rb_obj_class(indent)) {
|
862
|
-
#else
|
863
|
-
if (rb_cFixnum != rb_obj_class(indent)) {
|
864
|
-
#endif
|
865
831
|
rb_raise(ox_parse_error_class, "indent must be a fixnum.\n");
|
866
832
|
}
|
867
833
|
|
data/ext/ox/dump.c
CHANGED
@@ -159,12 +159,8 @@ static Type obj_class_code(VALUE obj) {
|
|
159
159
|
case T_OBJECT: return (ox_document_clas == clas || ox_element_clas == clas) ? RawCode : ObjectCode;
|
160
160
|
case T_REGEXP: return RegexpCode;
|
161
161
|
case T_BIGNUM: return BignumCode;
|
162
|
-
#ifdef T_COMPLEX
|
163
162
|
case T_COMPLEX: return ComplexCode;
|
164
|
-
#endif
|
165
|
-
#ifdef T_RATIONAL
|
166
163
|
case T_RATIONAL: return RationalCode;
|
167
|
-
#endif
|
168
164
|
case T_CLASS: return ClassCode;
|
169
165
|
default: return 0;
|
170
166
|
}
|
@@ -440,19 +436,13 @@ inline static void dump_num(Out out, VALUE obj) {
|
|
440
436
|
}
|
441
437
|
|
442
438
|
static void dump_time_thin(Out out, VALUE obj) {
|
443
|
-
char
|
444
|
-
char
|
445
|
-
#if HAVE_RB_TIME_TIMESPEC
|
439
|
+
char buf[64];
|
440
|
+
char *b = buf + sizeof(buf) - 1;
|
446
441
|
struct timespec ts = rb_time_timespec(obj);
|
447
442
|
time_t sec = ts.tv_sec;
|
448
443
|
long nsec = ts.tv_nsec;
|
449
|
-
|
450
|
-
|
451
|
-
long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
|
452
|
-
// long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
|
453
|
-
#endif
|
454
|
-
char *dot = b - 10;
|
455
|
-
long size;
|
444
|
+
char *dot = b - 10;
|
445
|
+
long size;
|
456
446
|
|
457
447
|
*b-- = '\0';
|
458
448
|
for (; dot < b; b--, nsec /= 10) {
|
@@ -495,18 +485,12 @@ static void dump_date(Out out, VALUE obj) {
|
|
495
485
|
}
|
496
486
|
|
497
487
|
static void dump_time_xsd(Out out, VALUE obj) {
|
498
|
-
struct tm
|
499
|
-
#if HAVE_RB_TIME_TIMESPEC
|
488
|
+
struct tm *tm;
|
500
489
|
struct timespec ts = rb_time_timespec(obj);
|
501
490
|
time_t sec = ts.tv_sec;
|
502
491
|
long nsec = ts.tv_nsec;
|
503
|
-
|
504
|
-
|
505
|
-
long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
|
506
|
-
// long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
|
507
|
-
#endif
|
508
|
-
int tzhour, tzmin;
|
509
|
-
char tzsign = '+';
|
492
|
+
int tzhour, tzmin;
|
493
|
+
char tzsign = '+';
|
510
494
|
|
511
495
|
if (out->end - out->cur <= 33) {
|
512
496
|
grow(out, 33);
|
@@ -777,7 +761,7 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
777
761
|
e.indent = -1;
|
778
762
|
out->w_end(out, &e);
|
779
763
|
} else if (0 == strcmp("BigDecimal", classname)) {
|
780
|
-
volatile VALUE rs =
|
764
|
+
volatile VALUE rs = rb_String(obj);
|
781
765
|
|
782
766
|
e.type = BigDecimalCode;
|
783
767
|
out->w_start(out, &e);
|
@@ -821,13 +805,8 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
821
805
|
} else {
|
822
806
|
char num_buf[16];
|
823
807
|
int d2 = depth + 1;
|
824
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
825
808
|
long i;
|
826
|
-
long cnt
|
827
|
-
#else // UNIFY_FIXNUM_AND_INTEGER
|
828
|
-
int i;
|
829
|
-
int cnt = (int)RSTRUCT_LEN(obj);
|
830
|
-
#endif // UNIFY_FIXNUM_AND_INTEGER
|
809
|
+
long cnt = NUM2LONG(rb_struct_size(obj));
|
831
810
|
e.type = StructCode;
|
832
811
|
e.clas.str = rb_class2name(clas);
|
833
812
|
e.clas.len = strlen(e.clas.str);
|
@@ -866,7 +845,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
866
845
|
dump_gen_element(obj, depth + 1, out);
|
867
846
|
out->w_end(out, &e);
|
868
847
|
} else { /* Object */
|
869
|
-
#if HAVE_RB_IVAR_FOREACH
|
870
848
|
e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
|
871
849
|
cnt = (int)rb_ivar_count(obj);
|
872
850
|
e.closed = (0 >= cnt);
|
@@ -879,29 +857,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
879
857
|
out->depth = od;
|
880
858
|
out->w_end(out, &e);
|
881
859
|
}
|
882
|
-
#else
|
883
|
-
volatile VALUE vars = rb_obj_instance_variables(obj);
|
884
|
-
// volatile VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0);
|
885
|
-
|
886
|
-
e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
|
887
|
-
cnt = (int)RARRAY_LEN(vars);
|
888
|
-
e.closed = (0 >= cnt);
|
889
|
-
out->w_start(out, &e);
|
890
|
-
if (0 < cnt) {
|
891
|
-
const VALUE *np = RARRAY_PTR(vars);
|
892
|
-
ID vid;
|
893
|
-
unsigned int od = out->depth;
|
894
|
-
int i;
|
895
|
-
|
896
|
-
out->depth = depth + 1;
|
897
|
-
for (i = cnt; 0 < i; i--, np++) {
|
898
|
-
vid = rb_to_id(*np);
|
899
|
-
dump_var(vid, rb_ivar_get(obj, vid), out);
|
900
|
-
}
|
901
|
-
out->depth = od;
|
902
|
-
out->w_end(out, &e);
|
903
|
-
}
|
904
|
-
#endif
|
905
860
|
}
|
906
861
|
break;
|
907
862
|
}
|
@@ -940,7 +895,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
940
895
|
out->w_end(out, &e);
|
941
896
|
break;
|
942
897
|
}
|
943
|
-
#ifdef T_COMPLEX
|
944
898
|
case T_COMPLEX: e.type = ComplexCode; out->w_start(out, &e);
|
945
899
|
#ifdef RCOMPLEX
|
946
900
|
dump_obj(0, RCOMPLEX(obj)->real, depth + 1, out);
|
@@ -951,8 +905,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
951
905
|
#endif
|
952
906
|
out->w_end(out, &e);
|
953
907
|
break;
|
954
|
-
#endif
|
955
|
-
#ifdef T_RATIONAL
|
956
908
|
case T_RATIONAL: e.type = RationalCode; out->w_start(out, &e);
|
957
909
|
#ifdef RRATIONAL
|
958
910
|
dump_obj(0, RRATIONAL(obj)->num, depth + 1, out);
|
@@ -963,7 +915,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
963
915
|
#endif
|
964
916
|
out->w_end(out, &e);
|
965
917
|
break;
|
966
|
-
#endif
|
967
918
|
case T_CLASS: {
|
968
919
|
e.type = ClassCode;
|
969
920
|
e.clas.str = rb_class2name(obj);
|
data/ext/ox/extconf.rb
CHANGED
@@ -32,14 +32,9 @@ CONFIG['warnflags'].slice!(/ -Wsuggest-attribute=format/)
|
|
32
32
|
CONFIG['warnflags'].slice!(/ -Wdeclaration-after-statement/)
|
33
33
|
CONFIG['warnflags'].slice!(/ -Wmissing-noreturn/)
|
34
34
|
|
35
|
-
have_func('rb_time_timespec')
|
36
|
-
have_func('rb_struct_alloc_noinit')
|
37
|
-
have_func('rb_obj_encoding')
|
38
|
-
have_func('rb_ivar_foreach')
|
39
35
|
have_func('rb_ext_ractor_safe', 'ruby.h')
|
40
36
|
have_func('pthread_mutex_init')
|
41
37
|
have_func('rb_enc_interned_str')
|
42
|
-
have_func('rb_time_nano_new')
|
43
38
|
have_func('index')
|
44
39
|
|
45
40
|
have_header('ruby/st.h')
|
data/ext/ox/gen_load.c
CHANGED
@@ -73,9 +73,7 @@ static void create_doc(PInfo pi) {
|
|
73
73
|
|
74
74
|
helper_stack_init(&pi->helpers);
|
75
75
|
doc = rb_obj_alloc(ox_document_clas);
|
76
|
-
#ifdef RB_GC_GUARD
|
77
76
|
RB_GC_GUARD(doc);
|
78
|
-
#endif
|
79
77
|
nodes = rb_ary_new();
|
80
78
|
rb_ivar_set(doc, ox_attributes_id, rb_hash_new());
|
81
79
|
rb_ivar_set(doc, ox_nodes_id, nodes);
|
@@ -104,7 +102,7 @@ static void create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
|
|
104
102
|
VALUE rstr = rb_str_new2(attrs->name);
|
105
103
|
|
106
104
|
rb_enc_associate(rstr, pi->options->rb_enc);
|
107
|
-
sym =
|
105
|
+
sym = rb_str_intern(rstr);
|
108
106
|
} else {
|
109
107
|
sym = ID2SYM(rb_intern(attrs->name));
|
110
108
|
}
|
data/ext/ox/obj_load.c
CHANGED
@@ -106,11 +106,7 @@ inline static VALUE structname2obj(const char *name) {
|
|
106
106
|
}
|
107
107
|
}
|
108
108
|
ost = rb_const_get(ox_struct_class, rb_intern(s));
|
109
|
-
#if HAVE_RB_STRUCT_ALLOC_NOINIT
|
110
109
|
return rb_struct_alloc_noinit(ost);
|
111
|
-
#else
|
112
|
-
return rb_struct_new(ost);
|
113
|
-
#endif
|
114
110
|
}
|
115
111
|
|
116
112
|
inline static VALUE parse_ulong(const char *s, PInfo pi) {
|
@@ -643,27 +639,21 @@ static void end_element(PInfo pi, const char *ename) {
|
|
643
639
|
rb_hash_aset(gh->obj, ph->obj, h->obj);
|
644
640
|
} break;
|
645
641
|
case ComplexCode:
|
646
|
-
#ifdef T_COMPLEX
|
647
642
|
if (Qundef == ph->obj) {
|
648
643
|
ph->obj = h->obj;
|
649
644
|
} else {
|
650
645
|
ph->obj = rb_complex_new(ph->obj, h->obj);
|
651
646
|
}
|
652
|
-
#else
|
653
|
-
set_error(&pi->err, "Complex Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
|
654
|
-
return;
|
655
|
-
#endif
|
656
647
|
break;
|
657
648
|
case RationalCode: {
|
658
649
|
if (Qundef == h->obj || RUBY_T_FIXNUM != rb_type(h->obj)) {
|
659
650
|
set_error(&pi->err, "Invalid object format", pi->str, pi->s);
|
660
651
|
return;
|
661
652
|
}
|
662
|
-
#ifdef T_RATIONAL
|
663
653
|
if (Qundef == ph->obj) {
|
664
654
|
ph->obj = h->obj;
|
665
655
|
} else {
|
666
|
-
if (Qundef == ph->obj || RUBY_T_FIXNUM != rb_type(
|
656
|
+
if (Qundef == ph->obj || RUBY_T_FIXNUM != rb_type(ph->obj)) {
|
667
657
|
set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
|
668
658
|
return;
|
669
659
|
}
|
@@ -673,10 +663,6 @@ static void end_element(PInfo pi, const char *ename) {
|
|
673
663
|
ph->obj = rb_rational_new(ph->obj, h->obj);
|
674
664
|
#endif
|
675
665
|
}
|
676
|
-
#else
|
677
|
-
set_error(&pi->err, "Rational Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
|
678
|
-
return;
|
679
|
-
#endif
|
680
666
|
break;
|
681
667
|
}
|
682
668
|
default:
|
@@ -719,11 +705,7 @@ static VALUE parse_double_time(const char *text, VALUE clas) {
|
|
719
705
|
for (; text - dot <= 9; text++) {
|
720
706
|
v2 *= 10;
|
721
707
|
}
|
722
|
-
#if HAVE_RB_TIME_NANO_NEW
|
723
708
|
return rb_time_nano_new(v, v2);
|
724
|
-
#else
|
725
|
-
return rb_time_new(v, v2 / 1000);
|
726
|
-
#endif
|
727
709
|
}
|
728
710
|
|
729
711
|
typedef struct _tp {
|
@@ -774,11 +756,7 @@ static VALUE parse_xsd_time(const char *text, VALUE clas) {
|
|
774
756
|
tm.tm_hour = (int)cargs[3];
|
775
757
|
tm.tm_min = (int)cargs[4];
|
776
758
|
tm.tm_sec = (int)cargs[5];
|
777
|
-
#if HAVE_RB_TIME_NANO_NEW
|
778
759
|
return rb_time_nano_new(mktime(&tm), cargs[6]);
|
779
|
-
#else
|
780
|
-
return rb_time_new(mktime(&tm), cargs[6] / 1000);
|
781
|
-
#endif
|
782
760
|
}
|
783
761
|
|
784
762
|
// debug functions
|
@@ -816,7 +794,7 @@ static void debug_stack(PInfo pi, const char *comment) {
|
|
816
794
|
if (HashCode == h->type) {
|
817
795
|
VALUE v;
|
818
796
|
|
819
|
-
v =
|
797
|
+
v = rb_String(h->var);
|
820
798
|
key = StringValuePtr(v);
|
821
799
|
} else if (ObjectCode == (h - 1)->type || ExceptionCode == (h - 1)->type ||
|
822
800
|
RangeCode == (h - 1)->type || StructCode == (h - 1)->type) {
|
data/ext/ox/ox.c
CHANGED
@@ -73,11 +73,6 @@ ID ox_start_element_id;
|
|
73
73
|
ID ox_string_id;
|
74
74
|
ID ox_text_id;
|
75
75
|
ID ox_to_c_id;
|
76
|
-
ID ox_to_s_id;
|
77
|
-
ID ox_to_sym_id;
|
78
|
-
ID ox_tv_nsec_id;
|
79
|
-
ID ox_tv_sec_id;
|
80
|
-
ID ox_tv_usec_id;
|
81
76
|
ID ox_value_id;
|
82
77
|
|
83
78
|
VALUE ox_encoding_sym;
|
@@ -687,17 +682,13 @@ static VALUE to_obj(VALUE self, VALUE ruby_xml) {
|
|
687
682
|
xml = ALLOCA_N(char, len);
|
688
683
|
}
|
689
684
|
memcpy(xml, x, len);
|
690
|
-
#ifdef RB_GC_GUARD
|
691
685
|
rb_gc_disable();
|
692
|
-
#endif
|
693
686
|
obj = ox_parse(xml, len - 1, ox_obj_callbacks, 0, &options, &err);
|
694
687
|
if (SMALL_XML < len) {
|
695
688
|
xfree(xml);
|
696
689
|
}
|
697
|
-
#ifdef RB_GC_GUARD
|
698
690
|
RB_GC_GUARD(obj);
|
699
691
|
rb_gc_enable();
|
700
|
-
#endif
|
701
692
|
if (err_has(&err)) {
|
702
693
|
ox_err_raise(&err);
|
703
694
|
}
|
@@ -740,130 +731,123 @@ static VALUE to_gen(VALUE self, VALUE ruby_xml) {
|
|
740
731
|
return obj;
|
741
732
|
}
|
742
733
|
|
743
|
-
static
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
if (
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
options.mode = HashMode;
|
762
|
-
} else if (hash_no_attrs_sym == v) {
|
763
|
-
options.mode = HashNoAttrMode;
|
764
|
-
} else {
|
765
|
-
rb_raise(ox_parse_error_class, ":mode must be :generic, :object, :limited, :hash, :hash_no_attrs.\n");
|
766
|
-
}
|
767
|
-
}
|
768
|
-
if (Qnil != (v = rb_hash_lookup(h, effort_sym))) {
|
769
|
-
if (auto_define_sym == v) {
|
770
|
-
options.effort = AutoEffort;
|
771
|
-
} else if (tolerant_sym == v) {
|
772
|
-
options.effort = TolerantEffort;
|
773
|
-
} else if (strict_sym == v) {
|
774
|
-
options.effort = StrictEffort;
|
775
|
-
} else {
|
776
|
-
rb_raise(ox_parse_error_class, ":effort must be :strict, :tolerant, or :auto_define.\n");
|
777
|
-
}
|
778
|
-
}
|
779
|
-
if (Qnil != (v = rb_hash_lookup(h, skip_sym))) {
|
780
|
-
if (skip_none_sym == v) {
|
781
|
-
options.skip = NoSkip;
|
782
|
-
} else if (skip_off_sym == v) {
|
783
|
-
options.skip = OffSkip;
|
784
|
-
} else if (skip_return_sym == v) {
|
785
|
-
options.skip = CrSkip;
|
786
|
-
} else if (skip_white_sym == v) {
|
787
|
-
options.skip = SpcSkip;
|
788
|
-
} else {
|
789
|
-
rb_raise(ox_parse_error_class, ":skip must be :skip_none, :skip_return, :skip_white, or :skip_off.\n");
|
790
|
-
}
|
791
|
-
}
|
792
|
-
|
793
|
-
if (Qnil != (v = rb_hash_lookup(h, trace_sym))) {
|
794
|
-
Check_Type(v, T_FIXNUM);
|
795
|
-
options.trace = FIX2INT(v);
|
796
|
-
}
|
797
|
-
if (Qnil != (v = rb_hash_lookup(h, symbolize_keys_sym))) {
|
798
|
-
options.sym_keys = (Qfalse == v) ? No : Yes;
|
734
|
+
static int load_options_cb(VALUE k, VALUE v, VALUE opts) {
|
735
|
+
Options copts = (Options)opts;
|
736
|
+
|
737
|
+
if (mode_sym == k) {
|
738
|
+
if (object_sym == v) {
|
739
|
+
copts->mode = ObjMode;
|
740
|
+
} else if (optimized_sym == v) {
|
741
|
+
copts->mode = ObjMode;
|
742
|
+
} else if (generic_sym == v) {
|
743
|
+
copts->mode = GenMode;
|
744
|
+
} else if (limited_sym == v) {
|
745
|
+
copts->mode = LimMode;
|
746
|
+
} else if (hash_sym == v) {
|
747
|
+
copts->mode = HashMode;
|
748
|
+
} else if (hash_no_attrs_sym == v) {
|
749
|
+
copts->mode = HashNoAttrMode;
|
750
|
+
} else {
|
751
|
+
rb_raise(ox_parse_error_class, ":mode must be :generic, :object, :limited, :hash, :hash_no_attrs.\n");
|
799
752
|
}
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
if (
|
804
|
-
|
753
|
+
} else if (effort_sym == k) {
|
754
|
+
if (auto_define_sym == v) {
|
755
|
+
copts->effort = AutoEffort;
|
756
|
+
} else if (tolerant_sym == v) {
|
757
|
+
copts->effort = TolerantEffort;
|
758
|
+
} else if (strict_sym == v) {
|
759
|
+
copts->effort = StrictEffort;
|
760
|
+
} else {
|
761
|
+
rb_raise(ox_parse_error_class, ":effort must be :strict, :tolerant, or :auto_define.\n");
|
805
762
|
}
|
806
|
-
|
807
|
-
|
763
|
+
} else if (skip_sym == k) {
|
764
|
+
if (skip_none_sym == v) {
|
765
|
+
copts->skip = NoSkip;
|
766
|
+
} else if (skip_off_sym == v) {
|
767
|
+
copts->skip = OffSkip;
|
768
|
+
} else if (skip_return_sym == v) {
|
769
|
+
copts->skip = CrSkip;
|
770
|
+
} else if (skip_white_sym == v) {
|
771
|
+
copts->skip = SpcSkip;
|
772
|
+
} else {
|
773
|
+
rb_raise(ox_parse_error_class, ":skip must be :skip_none, :skip_return, :skip_white, or :skip_off.\n");
|
808
774
|
}
|
809
|
-
|
810
|
-
v
|
775
|
+
} else if (trace_sym == k) {
|
776
|
+
Check_Type(v, T_FIXNUM);
|
777
|
+
copts->trace = FIX2INT(v);
|
778
|
+
} else if (symbolize_keys_sym == k) {
|
779
|
+
copts->sym_keys = (Qfalse == v) ? No : Yes;
|
780
|
+
} else if (element_key_mod_sym == k) {
|
781
|
+
copts->element_key_mod = v;
|
782
|
+
} else if (attr_key_mod_sym == k) {
|
783
|
+
copts->attr_key_mod = v;
|
784
|
+
} else if (convert_special_sym == k) {
|
785
|
+
copts->convert_special = (Qfalse != v);
|
786
|
+
} else if (no_empty_sym == k) {
|
787
|
+
copts->no_empty = (Qfalse != v);
|
788
|
+
} else if (invalid_replace_sym == k) {
|
811
789
|
if (Qnil == v) {
|
812
|
-
|
813
|
-
options.allow_invalid = Yes;
|
814
|
-
}
|
790
|
+
copts->allow_invalid = Yes;
|
815
791
|
} else {
|
816
792
|
long slen;
|
817
793
|
|
818
794
|
Check_Type(v, T_STRING);
|
819
795
|
slen = RSTRING_LEN(v);
|
820
|
-
if (sizeof(
|
796
|
+
if (sizeof(copts->inv_repl) - 2 < (size_t)slen) {
|
821
797
|
rb_raise(ox_parse_error_class,
|
822
798
|
":invalid_replace can be no longer than %d characters.",
|
823
|
-
(int)sizeof(
|
799
|
+
(int)sizeof(copts->inv_repl) - 2);
|
824
800
|
}
|
825
|
-
strncpy(
|
826
|
-
|
827
|
-
*
|
828
|
-
|
801
|
+
strncpy(copts->inv_repl + 1, StringValuePtr(v), sizeof(copts->inv_repl) - 1);
|
802
|
+
copts->inv_repl[sizeof(copts->inv_repl) - 1] = '\0';
|
803
|
+
*copts->inv_repl = (char)slen;
|
804
|
+
copts->allow_invalid = No;
|
829
805
|
}
|
830
|
-
|
806
|
+
} else if (strip_namespace_sym == k) {
|
831
807
|
if (Qfalse == v) {
|
832
|
-
*
|
808
|
+
*copts->strip_ns = '\0';
|
833
809
|
} else if (Qtrue == v) {
|
834
|
-
*
|
835
|
-
|
810
|
+
*copts->strip_ns = '*';
|
811
|
+
copts->strip_ns[1] = '\0';
|
836
812
|
} else if (Qnil != v) {
|
837
813
|
long slen;
|
838
814
|
|
839
815
|
Check_Type(v, T_STRING);
|
840
816
|
slen = RSTRING_LEN(v);
|
841
|
-
if (sizeof(
|
817
|
+
if (sizeof(copts->strip_ns) - 1 < (size_t)slen) {
|
842
818
|
rb_raise(ox_parse_error_class,
|
843
819
|
":strip_namespace can be no longer than %d characters.",
|
844
|
-
(int)sizeof(
|
820
|
+
(int)sizeof(copts->strip_ns) - 1);
|
845
821
|
}
|
846
|
-
strncpy(
|
847
|
-
|
822
|
+
strncpy(copts->strip_ns, StringValuePtr(v), sizeof(copts->strip_ns) - 1);
|
823
|
+
copts->strip_ns[sizeof(copts->strip_ns) - 1] = '\0';
|
848
824
|
}
|
849
|
-
|
850
|
-
|
851
|
-
long slen;
|
825
|
+
} else if (margin_sym == k) {
|
826
|
+
long slen;
|
852
827
|
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
}
|
860
|
-
strncpy(options.margin, StringValuePtr(v), sizeof(options.margin) - 1);
|
861
|
-
options.margin[sizeof(options.margin) - 1] = '\0';
|
862
|
-
options.margin_len = strlen(options.margin);
|
863
|
-
}
|
864
|
-
if (Qnil != (v = rb_hash_lookup(h, with_cdata_sym))) {
|
865
|
-
options.with_cdata = (Qtrue == v);
|
828
|
+
Check_Type(v, T_STRING);
|
829
|
+
slen = RSTRING_LEN(v);
|
830
|
+
if (sizeof(copts->margin) - 1 < (size_t)slen) {
|
831
|
+
rb_raise(ox_parse_error_class,
|
832
|
+
":margin can be no longer than %d characters.",
|
833
|
+
(int)sizeof(copts->margin) - 1);
|
866
834
|
}
|
835
|
+
strncpy(copts->margin, StringValuePtr(v), sizeof(copts->margin) - 1);
|
836
|
+
copts->margin[sizeof(copts->margin) - 1] = '\0';
|
837
|
+
copts->margin_len = strlen(copts->margin);
|
838
|
+
} else if (with_cdata_sym == k) {
|
839
|
+
copts->with_cdata = (Qtrue == v);
|
840
|
+
}
|
841
|
+
|
842
|
+
return ST_CONTINUE;
|
843
|
+
}
|
844
|
+
|
845
|
+
static VALUE load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, Err err) {
|
846
|
+
VALUE obj;
|
847
|
+
struct _options options = ox_default_options;
|
848
|
+
|
849
|
+
if (1 == argc && rb_cHash == rb_obj_class(*argv)) {
|
850
|
+
rb_hash_foreach(*argv, load_options_cb, (VALUE)&options);
|
867
851
|
}
|
868
852
|
if ('\0' == *options.encoding) {
|
869
853
|
if (Qnil != encoding) {
|
@@ -877,14 +861,10 @@ static VALUE load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALU
|
|
877
861
|
xml = defuse_bom(xml, &options);
|
878
862
|
switch (options.mode) {
|
879
863
|
case ObjMode:
|
880
|
-
#ifdef RB_GC_GUARD
|
881
864
|
rb_gc_disable();
|
882
|
-
#endif
|
883
865
|
obj = ox_parse(xml, len, ox_obj_callbacks, 0, &options, err);
|
884
|
-
#ifdef RB_GC_GUARD
|
885
866
|
RB_GC_GUARD(obj);
|
886
867
|
rb_gc_enable();
|
887
|
-
#endif
|
888
868
|
break;
|
889
869
|
case GenMode: obj = ox_parse(xml, len, ox_gen_callbacks, 0, &options, err); break;
|
890
870
|
case LimMode: obj = ox_parse(xml, len, ox_limited_callbacks, 0, &options, err); break;
|
@@ -952,11 +932,7 @@ static VALUE load_str(int argc, VALUE *argv, VALUE self) {
|
|
952
932
|
} else {
|
953
933
|
xml = ALLOCA_N(char, len);
|
954
934
|
}
|
955
|
-
#if HAVE_RB_OBJ_ENCODING
|
956
935
|
encoding = rb_obj_encoding(*argv);
|
957
|
-
#else
|
958
|
-
encoding = Qnil;
|
959
|
-
#endif
|
960
936
|
memcpy(xml, StringValuePtr(*argv), len);
|
961
937
|
xml[len - 1] = '\0';
|
962
938
|
obj = load(xml, len - 1, argc - 1, argv + 1, self, encoding, &err);
|
@@ -1201,21 +1177,13 @@ static void parse_dump_options(VALUE ropts, Options copts) {
|
|
1201
1177
|
VALUE v;
|
1202
1178
|
|
1203
1179
|
if (Qnil != (v = rb_hash_lookup(ropts, ox_indent_sym))) {
|
1204
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
1205
1180
|
if (rb_cInteger != rb_obj_class(v) && T_FIXNUM != rb_type(v)) {
|
1206
|
-
#else
|
1207
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
1208
|
-
#endif
|
1209
1181
|
rb_raise(ox_parse_error_class, ":indent must be a Fixnum.\n");
|
1210
1182
|
}
|
1211
1183
|
copts->indent = NUM2INT(v);
|
1212
1184
|
}
|
1213
1185
|
if (Qnil != (v = rb_hash_lookup(ropts, trace_sym))) {
|
1214
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
1215
1186
|
if (rb_cInteger != rb_obj_class(v) && T_FIXNUM != rb_type(v)) {
|
1216
|
-
#else
|
1217
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
1218
|
-
#endif
|
1219
1187
|
rb_raise(ox_parse_error_class, ":trace must be a Fixnum.\n");
|
1220
1188
|
}
|
1221
1189
|
copts->trace = NUM2INT(v);
|
@@ -1469,11 +1437,6 @@ void Init_ox() {
|
|
1469
1437
|
ox_string_id = rb_intern("string");
|
1470
1438
|
ox_text_id = rb_intern("text");
|
1471
1439
|
ox_to_c_id = rb_intern("to_c");
|
1472
|
-
ox_to_s_id = rb_intern("to_s");
|
1473
|
-
ox_to_sym_id = rb_intern("to_sym");
|
1474
|
-
ox_tv_nsec_id = rb_intern("tv_nsec");
|
1475
|
-
ox_tv_sec_id = rb_intern("tv_sec");
|
1476
|
-
ox_tv_usec_id = rb_intern("tv_usec");
|
1477
1440
|
ox_value_id = rb_intern("value");
|
1478
1441
|
|
1479
1442
|
encoding_id = rb_intern("encoding");
|
@@ -1675,8 +1638,6 @@ _ox_raise_error(const char *msg, const char *xml, const char *current, const cha
|
|
1675
1638
|
xline++;
|
1676
1639
|
}
|
1677
1640
|
}
|
1678
|
-
#ifdef RB_GC_GUARD
|
1679
1641
|
rb_gc_enable();
|
1680
|
-
#endif
|
1681
1642
|
rb_raise(ox_parse_error_class, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
|
1682
1643
|
}
|
data/ext/ox/ox.h
CHANGED
@@ -205,11 +205,6 @@ extern ID ox_start_element_id;
|
|
205
205
|
extern ID ox_string_id;
|
206
206
|
extern ID ox_text_id;
|
207
207
|
extern ID ox_to_c_id;
|
208
|
-
extern ID ox_to_s_id;
|
209
|
-
extern ID ox_to_sym_id;
|
210
|
-
extern ID ox_tv_sec_id;
|
211
|
-
extern ID ox_tv_nsec_id;
|
212
|
-
extern ID ox_tv_usec_id;
|
213
208
|
extern ID ox_value_id;
|
214
209
|
|
215
210
|
extern rb_encoding *ox_utf8_encoding;
|
data/ext/ox/sax.c
CHANGED
@@ -55,7 +55,7 @@ static char read_text(SaxDrive dr);
|
|
55
55
|
static char read_jump(SaxDrive dr, const char *pat);
|
56
56
|
static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req, Hint h);
|
57
57
|
static char read_name_token(SaxDrive dr);
|
58
|
-
static char read_quoted_value(SaxDrive dr);
|
58
|
+
static char read_quoted_value(SaxDrive dr, bool inst);
|
59
59
|
|
60
60
|
static void hint_clear_empty(SaxDrive dr);
|
61
61
|
static Nv hint_try_close(SaxDrive dr, const char *name);
|
@@ -469,7 +469,7 @@ DONE:
|
|
469
469
|
Nv sp;
|
470
470
|
|
471
471
|
for (sp = dr->stack.tail - 1; dr->stack.head <= sp; sp--) {
|
472
|
-
snprintf(msg, sizeof(msg) - 1, "%selement '%s' not closed", EL_MISMATCH, sp
|
472
|
+
snprintf(msg, sizeof(msg) - 1, "%selement '%s' not closed", EL_MISMATCH, nv_name(sp));
|
473
473
|
ox_sax_drive_error_at(dr, msg, dr->buf.pos, dr->buf.line, dr->buf.col);
|
474
474
|
end_element_cb(dr, sp->val, dr->buf.pos, dr->buf.line, dr->buf.col, sp->hint);
|
475
475
|
}
|
@@ -1219,6 +1219,7 @@ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml,
|
|
1219
1219
|
c = buf_next_non_white(&dr->buf);
|
1220
1220
|
}
|
1221
1221
|
if ('=' != c) {
|
1222
|
+
// TBD allow in smart mode
|
1222
1223
|
if (eq_req) {
|
1223
1224
|
dr->err = 1;
|
1224
1225
|
return c;
|
@@ -1230,7 +1231,7 @@ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml,
|
|
1230
1231
|
pos = dr->buf.pos + 1;
|
1231
1232
|
line = dr->buf.line;
|
1232
1233
|
col = dr->buf.col + 1;
|
1233
|
-
c = read_quoted_value(dr);
|
1234
|
+
c = read_quoted_value(dr, '?' == termc);
|
1234
1235
|
attr_value = dr->buf.str;
|
1235
1236
|
|
1236
1237
|
if (is_encoding) {
|
@@ -1297,10 +1298,11 @@ static char read_name_token(SaxDrive dr) {
|
|
1297
1298
|
return '\0';
|
1298
1299
|
}
|
1299
1300
|
|
1300
|
-
/* The character after the quote or if there is no quote, the character after
|
1301
|
-
*
|
1301
|
+
/* The character after the quote or if there is no quote, the character after
|
1302
|
+
* the word is returned. dr->buf.tail is one past that. dr->buf.str will point
|
1303
|
+
* to the token which will be '\0' terminated.
|
1302
1304
|
*/
|
1303
|
-
static char read_quoted_value(SaxDrive dr) {
|
1305
|
+
static char read_quoted_value(SaxDrive dr, bool inst) {
|
1304
1306
|
char c;
|
1305
1307
|
|
1306
1308
|
c = buf_get(&dr->buf);
|
@@ -1324,19 +1326,27 @@ static char read_quoted_value(SaxDrive dr) {
|
|
1324
1326
|
}
|
1325
1327
|
// not quoted, look for something that terminates the string
|
1326
1328
|
dr->buf.str = dr->buf.tail - 1;
|
1327
|
-
|
1329
|
+
// TBD if smart or html then no error
|
1330
|
+
if (!(dr->options.smart && ox_hints_html() != dr->options.hints)) {
|
1331
|
+
ox_sax_drive_error(dr, WRONG_CHAR "attribute value not in quotes");
|
1332
|
+
}
|
1328
1333
|
while ('\0' != (c = buf_get(&dr->buf))) {
|
1329
1334
|
switch (c) {
|
1330
1335
|
case ' ':
|
1331
1336
|
// case '/':
|
1332
1337
|
case '>':
|
1333
|
-
case '?': // for instructions
|
1334
1338
|
case '\t':
|
1335
1339
|
case '\n':
|
1336
1340
|
case '\r':
|
1337
1341
|
*(dr->buf.tail - 1) = '\0'; /* terminate value */
|
1338
1342
|
// dr->buf.tail is in the correct position, one after the word terminator
|
1339
1343
|
return c;
|
1344
|
+
case '?': // for instructions
|
1345
|
+
if (inst) {
|
1346
|
+
*(dr->buf.tail - 1) = '\0'; /* terminate value */
|
1347
|
+
return c;
|
1348
|
+
}
|
1349
|
+
break;
|
1340
1350
|
default: break;
|
1341
1351
|
}
|
1342
1352
|
}
|
data/ext/ox/sax_as.c
CHANGED
@@ -43,11 +43,7 @@ static VALUE parse_double_time(const char *text) {
|
|
43
43
|
for (; text - dot <= 9; text++) {
|
44
44
|
v2 *= 10;
|
45
45
|
}
|
46
|
-
#if HAVE_RB_TIME_NANO_NEW
|
47
46
|
return rb_time_nano_new(v, v2);
|
48
|
-
#else
|
49
|
-
return rb_time_new(v, v2 / 1000);
|
50
|
-
#endif
|
51
47
|
}
|
52
48
|
|
53
49
|
typedef struct _tp {
|
@@ -102,11 +98,7 @@ static VALUE parse_xsd_time(const char *text) {
|
|
102
98
|
tm.tm_hour = (int)cargs[3];
|
103
99
|
tm.tm_min = (int)cargs[4];
|
104
100
|
tm.tm_sec = (int)cargs[5];
|
105
|
-
#if HAVE_RB_TIME_NANO_NEW
|
106
101
|
return rb_time_nano_new(mktime(&tm), cargs[6]);
|
107
|
-
#else
|
108
|
-
return rb_time_new(mktime(&tm), cargs[6] / 1000);
|
109
|
-
#endif
|
110
102
|
}
|
111
103
|
|
112
104
|
/* call-seq: as_s()
|
data/ext/ox/slotcache.c
CHANGED
@@ -145,7 +145,7 @@ static void slot_print(SlotCache c, unsigned int depth) {
|
|
145
145
|
vs = "undefined";
|
146
146
|
clas = "";
|
147
147
|
} else {
|
148
|
-
VALUE rs =
|
148
|
+
VALUE rs = rb_String((*cp)->value);
|
149
149
|
|
150
150
|
vs = StringValuePtr(rs);
|
151
151
|
clas = rb_class2name(rb_obj_class((*cp)->value));
|
data/lib/ox/version.rb
CHANGED
data/lib/ox/xmlrpc_adapter.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.14.
|
4
|
+
version: 2.14.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
12
|
-
dependencies:
|
11
|
+
date: 2023-07-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake-compiler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.2'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
13
33
|
description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
|
14
34
|
XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
|
15
35
|
It was designed to be an alternative to Nokogiri and other Ruby\nXML parsers for
|