ox 2.14.16 → 2.14.17
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.
- 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
|