ox 2.12.1 → 2.14.0
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 +44 -0
- data/README.md +31 -0
- data/ext/ox/builder.c +5 -1
- data/ext/ox/dump.c +6 -18
- data/ext/ox/extconf.rb +12 -34
- data/ext/ox/gen_load.c +18 -96
- data/ext/ox/hash_load.c +39 -12
- data/ext/ox/obj_load.c +14 -46
- data/ext/ox/ox.c +60 -48
- data/ext/ox/ox.h +7 -15
- data/ext/ox/parse.c +37 -44
- data/ext/ox/sax.c +43 -93
- data/ext/ox/sax.h +1 -3
- data/ext/ox/sax_as.c +2 -6
- data/ext/ox/sax_buf.c +1 -1
- data/ext/ox/special.c +346 -0
- data/ext/ox/special.h +1 -0
- data/lib/ox/element.rb +21 -11
- data/lib/ox/version.rb +1 -1
- metadata +5 -5
data/ext/ox/hash_load.c
CHANGED
@@ -74,19 +74,14 @@ unmark(PInfo pi, VALUE val) {
|
|
74
74
|
}
|
75
75
|
|
76
76
|
static void
|
77
|
-
|
77
|
+
add_str(PInfo pi, VALUE s) {
|
78
78
|
Helper parent = helper_stack_peek(&pi->helpers);
|
79
|
-
volatile VALUE s = rb_str_new2(text);
|
80
79
|
volatile VALUE a;
|
81
80
|
|
82
|
-
#if
|
81
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
83
82
|
if (0 != pi->options->rb_enc) {
|
84
83
|
rb_enc_associate(s, pi->options->rb_enc);
|
85
84
|
}
|
86
|
-
#elif HAS_PRIVATE_ENCODING
|
87
|
-
if (Qnil != pi->options->rb_enc) {
|
88
|
-
rb_funcall(s, ox_force_encoding_id, 1, pi->options->rb_enc);
|
89
|
-
}
|
90
85
|
#endif
|
91
86
|
switch (parent->type) {
|
92
87
|
case NoCode:
|
@@ -106,6 +101,16 @@ add_text(PInfo pi, char *text, int closed) {
|
|
106
101
|
}
|
107
102
|
}
|
108
103
|
|
104
|
+
static void
|
105
|
+
add_text(PInfo pi, char *text, int closed) {
|
106
|
+
add_str(pi, rb_str_new2(text));
|
107
|
+
}
|
108
|
+
|
109
|
+
static void
|
110
|
+
add_cdata(PInfo pi, const char *text, size_t len) {
|
111
|
+
add_str(pi, rb_str_new(text, len));
|
112
|
+
}
|
113
|
+
|
109
114
|
static void
|
110
115
|
add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
111
116
|
if (helper_stack_empty(&pi->helpers)) {
|
@@ -126,14 +131,10 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
126
131
|
key = rb_str_new2(attrs->name);
|
127
132
|
}
|
128
133
|
val = rb_str_new2(attrs->value);
|
129
|
-
#if
|
134
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
130
135
|
if (0 != pi->options->rb_enc) {
|
131
136
|
rb_enc_associate(val, pi->options->rb_enc);
|
132
137
|
}
|
133
|
-
#elif HAS_PRIVATE_ENCODING
|
134
|
-
if (Qnil != pi->options->rb_enc) {
|
135
|
-
rb_funcall(val, ox_force_encoding_id, 1, pi->options->rb_enc);
|
136
|
-
}
|
137
138
|
#endif
|
138
139
|
rb_hash_aset(h, key, val);
|
139
140
|
}
|
@@ -258,6 +259,19 @@ struct _parseCallbacks _ox_hash_callbacks = {
|
|
258
259
|
|
259
260
|
ParseCallbacks ox_hash_callbacks = &_ox_hash_callbacks;
|
260
261
|
|
262
|
+
struct _parseCallbacks _ox_hash_cdata_callbacks = {
|
263
|
+
NULL,
|
264
|
+
NULL,
|
265
|
+
NULL,
|
266
|
+
add_cdata,
|
267
|
+
add_text,
|
268
|
+
add_element,
|
269
|
+
end_element,
|
270
|
+
finish,
|
271
|
+
};
|
272
|
+
|
273
|
+
ParseCallbacks ox_hash_cdata_callbacks = &_ox_hash_cdata_callbacks;
|
274
|
+
|
261
275
|
struct _parseCallbacks _ox_hash_no_attrs_callbacks = {
|
262
276
|
NULL,
|
263
277
|
NULL,
|
@@ -270,3 +284,16 @@ struct _parseCallbacks _ox_hash_no_attrs_callbacks = {
|
|
270
284
|
};
|
271
285
|
|
272
286
|
ParseCallbacks ox_hash_no_attrs_callbacks = &_ox_hash_no_attrs_callbacks;
|
287
|
+
|
288
|
+
struct _parseCallbacks _ox_hash_no_attrs_cdata_callbacks = {
|
289
|
+
NULL,
|
290
|
+
NULL,
|
291
|
+
NULL,
|
292
|
+
add_cdata,
|
293
|
+
add_text,
|
294
|
+
add_element_no_attrs,
|
295
|
+
end_element_no_attrs,
|
296
|
+
NULL,
|
297
|
+
};
|
298
|
+
|
299
|
+
ParseCallbacks ox_hash_no_attrs_cdata_callbacks = &_ox_hash_no_attrs_cdata_callbacks;
|
data/ext/ox/obj_load.c
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
#include <time.h>
|
12
12
|
|
13
13
|
#include "ruby.h"
|
14
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
15
|
+
#include "ruby/encoding.h"
|
16
|
+
#endif
|
14
17
|
#include "base64.h"
|
15
18
|
#include "ox.h"
|
16
19
|
|
@@ -143,7 +146,6 @@ classname2obj(const char *name, PInfo pi, VALUE base_class) {
|
|
143
146
|
}
|
144
147
|
}
|
145
148
|
|
146
|
-
#if HAS_RSTRUCT
|
147
149
|
inline static VALUE
|
148
150
|
structname2obj(const char *name) {
|
149
151
|
VALUE ost;
|
@@ -159,16 +161,12 @@ structname2obj(const char *name) {
|
|
159
161
|
}
|
160
162
|
}
|
161
163
|
ost = rb_const_get(ox_struct_class, rb_intern(s));
|
162
|
-
|
163
|
-
#if HAS_ENCODING_SUPPORT
|
164
|
-
return rb_struct_alloc_noinit(ost);
|
165
|
-
#elif HAS_PRIVATE_ENCODING
|
164
|
+
#if HAVE_RB_STRUCT_ALLOC_NOINIT
|
166
165
|
return rb_struct_alloc_noinit(ost);
|
167
166
|
#else
|
168
167
|
return rb_struct_new(ost);
|
169
168
|
#endif
|
170
169
|
}
|
171
|
-
#endif
|
172
170
|
|
173
171
|
inline static VALUE
|
174
172
|
parse_ulong(const char *s, PInfo pi) {
|
@@ -239,6 +237,7 @@ static ID
|
|
239
237
|
get_var_sym_from_attrs(Attr a, void *encoding) {
|
240
238
|
for (; 0 != a->name; a++) {
|
241
239
|
if ('a' == *a->name && '\0' == *(a->name + 1)) {
|
240
|
+
name2var(a->value, encoding);
|
242
241
|
return name2var(a->value, encoding);
|
243
242
|
}
|
244
243
|
}
|
@@ -255,7 +254,6 @@ get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
|
255
254
|
return Qundef;
|
256
255
|
}
|
257
256
|
|
258
|
-
#if HAS_RSTRUCT
|
259
257
|
static VALUE
|
260
258
|
get_struct_from_attrs(Attr a) {
|
261
259
|
for (; 0 != a->name; a++) {
|
@@ -265,7 +263,6 @@ get_struct_from_attrs(Attr a) {
|
|
265
263
|
}
|
266
264
|
return Qundef;
|
267
265
|
}
|
268
|
-
#endif
|
269
266
|
|
270
267
|
static VALUE
|
271
268
|
get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
@@ -363,7 +360,7 @@ parse_regexp(const char *text) {
|
|
363
360
|
int options = 0;
|
364
361
|
|
365
362
|
te = text + strlen(text) - 1;
|
366
|
-
#
|
363
|
+
#ifdef ONIG_OPTION_IGNORECASE
|
367
364
|
for (; text < te && '/' != *te; te--) {
|
368
365
|
switch (*te) {
|
369
366
|
case 'i': options |= ONIG_OPTION_IGNORECASE; break;
|
@@ -379,18 +376,12 @@ parse_regexp(const char *text) {
|
|
379
376
|
static void
|
380
377
|
instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
381
378
|
if (0 == strcmp("xml", target)) {
|
382
|
-
#if
|
379
|
+
#if HAVE_RB_ENC_FIND
|
383
380
|
for (; 0 != attrs->name; attrs++) {
|
384
381
|
if (0 == strcmp("encoding", attrs->name)) {
|
385
382
|
pi->options->rb_enc = rb_enc_find(attrs->value);
|
386
383
|
}
|
387
384
|
}
|
388
|
-
#elif HAS_PRIVATE_ENCODING
|
389
|
-
for (; 0 != attrs->name; attrs++) {
|
390
|
-
if (0 == strcmp("encoding", attrs->name)) {
|
391
|
-
pi->options->rb_enc = rb_str_new2(attrs->value);
|
392
|
-
}
|
393
|
-
}
|
394
385
|
#endif
|
395
386
|
}
|
396
387
|
}
|
@@ -417,14 +408,10 @@ add_text(PInfo pi, char *text, int closed) {
|
|
417
408
|
case NoCode:
|
418
409
|
case StringCode:
|
419
410
|
h->obj = rb_str_new2(text);
|
420
|
-
#if
|
411
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
421
412
|
if (0 != pi->options->rb_enc) {
|
422
413
|
rb_enc_associate(h->obj, pi->options->rb_enc);
|
423
414
|
}
|
424
|
-
#elif HAS_PRIVATE_ENCODING
|
425
|
-
if (Qnil != pi->options->rb_enc) {
|
426
|
-
rb_funcall(h->obj, ox_force_encoding_id, 1, pi->options->rb_enc);
|
427
|
-
}
|
428
415
|
#endif
|
429
416
|
if (0 != pi->circ_array) {
|
430
417
|
circ_array_set(pi->circ_array, h->obj, (unsigned long)pi->id);
|
@@ -494,14 +481,10 @@ add_text(PInfo pi, char *text, int closed) {
|
|
494
481
|
|
495
482
|
from_base64(text, (uchar*)str);
|
496
483
|
v = rb_str_new(str, str_size);
|
497
|
-
#if
|
484
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
498
485
|
if (0 != pi->options->rb_enc) {
|
499
486
|
rb_enc_associate(v, pi->options->rb_enc);
|
500
487
|
}
|
501
|
-
#elif HAS_PRIVATE_ENCODING
|
502
|
-
if (0 != pi->options->rb_enc) {
|
503
|
-
rb_funcall(v, ox_force_encoding_id, 1, pi->options->rb_enc);
|
504
|
-
}
|
505
488
|
#endif
|
506
489
|
if (0 != pi->circ_array) {
|
507
490
|
circ_array_set(pi->circ_array, v, (unsigned long)h->obj);
|
@@ -542,11 +525,7 @@ add_text(PInfo pi, char *text, int closed) {
|
|
542
525
|
h->obj = rb_cstr_to_inum(text, 10, 1);
|
543
526
|
break;
|
544
527
|
case BigDecimalCode:
|
545
|
-
#if HAS_BIGDECIMAL
|
546
528
|
h->obj = rb_funcall(rb_cObject, ox_bigdecimal_id, 1, rb_str_new2(text));
|
547
|
-
#else
|
548
|
-
h->obj = Qnil;
|
549
|
-
#endif
|
550
529
|
break;
|
551
530
|
default:
|
552
531
|
h->obj = Qnil;
|
@@ -670,15 +649,10 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
670
649
|
}
|
671
650
|
break;
|
672
651
|
case StructCode:
|
673
|
-
#if HAS_RSTRUCT
|
674
652
|
h->obj = get_struct_from_attrs(attrs);
|
675
653
|
if (0 != pi->circ_array) {
|
676
654
|
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
677
655
|
}
|
678
|
-
#else
|
679
|
-
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
680
|
-
return;
|
681
|
-
#endif
|
682
656
|
break;
|
683
657
|
case ClassCode:
|
684
658
|
if (Qundef == (h->obj = get_class_from_attrs(attrs, pi, ox_bag_clas))) {
|
@@ -742,31 +716,29 @@ end_element(PInfo pi, const char *ename) {
|
|
742
716
|
case ExceptionCode:
|
743
717
|
case ObjectCode:
|
744
718
|
if (Qnil != ph->obj) {
|
745
|
-
if (0 == h->var) {
|
719
|
+
if (0 == h->var || NULL == rb_id2name(h->var )) {
|
746
720
|
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
747
721
|
return;
|
748
722
|
}
|
723
|
+
if (RUBY_T_OBJECT != rb_type(ph->obj)) {
|
724
|
+
set_error(&pi->err, "Corrupt object encoding", pi->str, pi->s);
|
725
|
+
return;
|
726
|
+
}
|
749
727
|
rb_ivar_set(ph->obj, h->var, h->obj);
|
750
728
|
}
|
751
729
|
break;
|
752
730
|
case StructCode:
|
753
|
-
#if HAS_RSTRUCT
|
754
731
|
if (0 == h->var) {
|
755
732
|
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
756
733
|
return;
|
757
734
|
}
|
758
735
|
rb_struct_aset(ph->obj, h->var, h->obj);
|
759
|
-
#else
|
760
|
-
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
761
|
-
return;
|
762
|
-
#endif
|
763
736
|
break;
|
764
737
|
case HashCode:
|
765
738
|
// put back h
|
766
739
|
helper_stack_push(&pi->helpers, h->var, h->obj, KeyCode);
|
767
740
|
break;
|
768
741
|
case RangeCode:
|
769
|
-
#if HAS_RSTRUCT
|
770
742
|
if (ox_beg_id == h->var) {
|
771
743
|
RSTRUCT_SET(ph->obj, 0, h->obj);
|
772
744
|
} else if (ox_end_id == h->var) {
|
@@ -777,10 +749,6 @@ end_element(PInfo pi, const char *ename) {
|
|
777
749
|
set_error(&pi->err, "Invalid range attribute", pi->str, pi->s);
|
778
750
|
return;
|
779
751
|
}
|
780
|
-
#else
|
781
|
-
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
782
|
-
return;
|
783
|
-
#endif
|
784
752
|
break;
|
785
753
|
case KeyCode:
|
786
754
|
{
|
data/ext/ox/ox.c
CHANGED
@@ -145,6 +145,7 @@ static VALUE symbolize_keys_sym;
|
|
145
145
|
static VALUE symbolize_sym;
|
146
146
|
static VALUE tolerant_sym;
|
147
147
|
static VALUE trace_sym;
|
148
|
+
static VALUE with_cdata_sym;
|
148
149
|
static VALUE with_dtd_sym;
|
149
150
|
static VALUE with_instruct_sym;
|
150
151
|
static VALUE with_xml_sym;
|
@@ -154,10 +155,8 @@ static VALUE element_key_mod_sym;
|
|
154
155
|
static ID encoding_id;
|
155
156
|
static ID has_key_id;
|
156
157
|
|
157
|
-
#if
|
158
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
158
159
|
rb_encoding *ox_utf8_encoding = 0;
|
159
|
-
#elif HAS_PRIVATE_ENCODING
|
160
|
-
VALUE ox_utf8_encoding = Qnil;
|
161
160
|
#else
|
162
161
|
void *ox_utf8_encoding = 0;
|
163
162
|
#endif
|
@@ -181,16 +180,13 @@ struct _options ox_default_options = {
|
|
181
180
|
true, // convert_special
|
182
181
|
No, // allow_invalid
|
183
182
|
false, // no_empty
|
183
|
+
false, // with_cdata
|
184
184
|
{ '\0' }, // inv_repl
|
185
185
|
{ '\0' }, // strip_ns
|
186
186
|
NULL, // html_hints
|
187
187
|
Qnil, // attr_key_mod;
|
188
188
|
Qnil, // element_key_mod;
|
189
|
-
#if HAS_PRIVATE_ENCODING
|
190
|
-
Qnil // rb_enc
|
191
|
-
#else
|
192
189
|
0 // rb_enc
|
193
|
-
#endif
|
194
190
|
};
|
195
191
|
|
196
192
|
extern ParseCallbacks ox_obj_callbacks;
|
@@ -198,7 +194,9 @@ extern ParseCallbacks ox_gen_callbacks;
|
|
198
194
|
extern ParseCallbacks ox_limited_callbacks;
|
199
195
|
extern ParseCallbacks ox_nomode_callbacks;
|
200
196
|
extern ParseCallbacks ox_hash_callbacks;
|
197
|
+
extern ParseCallbacks ox_hash_cdata_callbacks;
|
201
198
|
extern ParseCallbacks ox_hash_no_attrs_callbacks;
|
199
|
+
extern ParseCallbacks ox_hash_no_attrs_cdata_callbacks;
|
202
200
|
|
203
201
|
static void parse_dump_options(VALUE ropts, Options copts);
|
204
202
|
|
@@ -296,6 +294,7 @@ hints_to_overlay(Hints hints) {
|
|
296
294
|
* - _:convert_special_ [true|false|nil] flag indicating special characters like < are converted with the SAX parser
|
297
295
|
* - _:invalid_replace_ [nil|String] replacement string for invalid XML characters on dump. nil indicates include anyway as hex. A string, limited to 10 characters will replace the invalid character with the replace.
|
298
296
|
* - _:no_empty_ [true|false|nil] flag indicating there should be no empty elements in a dump
|
297
|
+
* - _:with_cdata_ [true|false] includes cdata in hash_load results
|
299
298
|
* - _:strip_namespace_ [String|true|false] false or "" results in no namespace stripping. A string of "*" or true will strip all namespaces. Any other non-empty string indicates that matching namespaces will be stripped.
|
300
299
|
* - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
|
301
300
|
* - _:active_ - make the normal callback for the element
|
@@ -330,6 +329,7 @@ get_def_opts(VALUE self) {
|
|
330
329
|
rb_hash_aset(opts, smart_sym, (Yes == ox_default_options.smart) ? Qtrue : ((No == ox_default_options.smart) ? Qfalse : Qnil));
|
331
330
|
rb_hash_aset(opts, convert_special_sym, (ox_default_options.convert_special) ? Qtrue : Qfalse);
|
332
331
|
rb_hash_aset(opts, no_empty_sym, (ox_default_options.no_empty) ? Qtrue : Qfalse);
|
332
|
+
rb_hash_aset(opts, with_cdata_sym, (ox_default_options.with_cdata) ? Qtrue : Qfalse);
|
333
333
|
switch (ox_default_options.mode) {
|
334
334
|
case ObjMode: rb_hash_aset(opts, mode_sym, object_sym); break;
|
335
335
|
case GenMode: rb_hash_aset(opts, mode_sym, generic_sym); break;
|
@@ -437,6 +437,7 @@ sax_html_overlay(VALUE self) {
|
|
437
437
|
* - _:smart_ [true|false|nil] flag indicating the SAX parser uses hints if available (use with html)
|
438
438
|
* - _:invalid_replace_ [nil|String] replacement string for invalid XML characters on dump. nil indicates include anyway as hex. A string, limited to 10 characters will replace the invalid character with the replace.
|
439
439
|
* - _:strip_namespace_ [nil|String|true|false] "" or false result in no namespace stripping. A string of "*" or true will strip all namespaces. Any other non-empty string indicates that matching namespaces will be stripped.
|
440
|
+
* - _:with_cdata_ [true|false] includes cdata in hash_load results
|
440
441
|
* - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
|
441
442
|
* - _:active_ - make the normal callback for the element
|
442
443
|
* - _:nest_ok_ - active but ignore nest check
|
@@ -470,11 +471,8 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
470
471
|
} else {
|
471
472
|
Check_Type(v, T_STRING);
|
472
473
|
strncpy(ox_default_options.encoding, StringValuePtr(v), sizeof(ox_default_options.encoding) - 1);
|
473
|
-
#if
|
474
|
+
#if HAVE_RB_ENC_FIND
|
474
475
|
ox_default_options.rb_enc = rb_enc_find(ox_default_options.encoding);
|
475
|
-
#elif HAS_PRIVATE_ENCODING
|
476
|
-
ox_default_options.rb_enc = rb_str_new2(ox_default_options.encoding);
|
477
|
-
rb_gc_register_address(&ox_default_options.rb_enc);
|
478
476
|
#endif
|
479
477
|
}
|
480
478
|
|
@@ -639,6 +637,10 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
639
637
|
rb_hash_foreach(v, set_overlay, (VALUE)ox_default_options.html_hints);
|
640
638
|
}
|
641
639
|
}
|
640
|
+
if (Qnil != (v = rb_hash_lookup(opts, with_cdata_sym))) {
|
641
|
+
ox_default_options.with_cdata = (Qtrue == v);
|
642
|
+
}
|
643
|
+
|
642
644
|
ox_default_options.element_key_mod = rb_hash_lookup2(opts, element_key_mod_sym, ox_default_options.element_key_mod);
|
643
645
|
ox_default_options.attr_key_mod = rb_hash_lookup2(opts, attr_key_mod_sym, ox_default_options.attr_key_mod);
|
644
646
|
|
@@ -674,14 +676,14 @@ to_obj(VALUE self, VALUE ruby_xml) {
|
|
674
676
|
xml = ALLOCA_N(char, len);
|
675
677
|
}
|
676
678
|
memcpy(xml, x, len);
|
677
|
-
#
|
679
|
+
#ifdef RB_GC_GUARD
|
678
680
|
rb_gc_disable();
|
679
681
|
#endif
|
680
682
|
obj = ox_parse(xml, len - 1, ox_obj_callbacks, 0, &options, &err);
|
681
683
|
if (SMALL_XML < len) {
|
682
684
|
xfree(xml);
|
683
685
|
}
|
684
|
-
#
|
686
|
+
#ifdef RB_GC_GUARD
|
685
687
|
RB_GC_GUARD(obj);
|
686
688
|
rb_gc_enable();
|
687
689
|
#endif
|
@@ -847,8 +849,11 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
847
849
|
options.margin[sizeof(options.margin) - 1] = '\0';
|
848
850
|
options.margin_len = strlen(options.margin);
|
849
851
|
}
|
852
|
+
if (Qnil != (v = rb_hash_lookup(h, with_cdata_sym))) {
|
853
|
+
options.with_cdata = (Qtrue == v);
|
854
|
+
}
|
850
855
|
}
|
851
|
-
#if
|
856
|
+
#if HAVE_RB_ENC_FIND
|
852
857
|
if ('\0' == *options.encoding) {
|
853
858
|
if (Qnil != encoding) {
|
854
859
|
options.rb_enc = rb_enc_from_index(rb_enc_get_index(encoding));
|
@@ -858,26 +863,15 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
858
863
|
} else if (0 == options.rb_enc) {
|
859
864
|
options.rb_enc = rb_enc_find(options.encoding);
|
860
865
|
}
|
861
|
-
#elif HAS_PRIVATE_ENCODING
|
862
|
-
if ('\0' == *options.encoding) {
|
863
|
-
if (Qnil != encoding) {
|
864
|
-
options.rb_enc = encoding;
|
865
|
-
} else {
|
866
|
-
options.rb_enc = Qnil;
|
867
|
-
}
|
868
|
-
} else if (0 == options.rb_enc) {
|
869
|
-
options.rb_enc = rb_str_new2(options.encoding);
|
870
|
-
rb_gc_register_address(&options.rb_enc);
|
871
|
-
}
|
872
866
|
#endif
|
873
867
|
xml = defuse_bom(xml, &options);
|
874
868
|
switch (options.mode) {
|
875
869
|
case ObjMode:
|
876
|
-
#
|
870
|
+
#ifdef RB_GC_GUARD
|
877
871
|
rb_gc_disable();
|
878
872
|
#endif
|
879
873
|
obj = ox_parse(xml, len, ox_obj_callbacks, 0, &options, err);
|
880
|
-
#
|
874
|
+
#ifdef RB_GC_GUARD
|
881
875
|
RB_GC_GUARD(obj);
|
882
876
|
rb_gc_enable();
|
883
877
|
#endif
|
@@ -889,10 +883,18 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
889
883
|
obj = ox_parse(xml, len, ox_limited_callbacks, 0, &options, err);
|
890
884
|
break;
|
891
885
|
case HashMode:
|
892
|
-
|
886
|
+
if (options.with_cdata) {
|
887
|
+
obj = ox_parse(xml, len, ox_hash_cdata_callbacks, 0, &options, err);
|
888
|
+
} else {
|
889
|
+
obj = ox_parse(xml, len, ox_hash_callbacks, 0, &options, err);
|
890
|
+
}
|
893
891
|
break;
|
894
892
|
case HashNoAttrMode:
|
895
|
-
|
893
|
+
if (options.with_cdata) {
|
894
|
+
obj = ox_parse(xml, len, ox_hash_no_attrs_cdata_callbacks, 0, &options, err);
|
895
|
+
} else {
|
896
|
+
obj = ox_parse(xml, len, ox_hash_no_attrs_callbacks, 0, &options, err);
|
897
|
+
}
|
896
898
|
break;
|
897
899
|
case NoMode:
|
898
900
|
obj = ox_parse(xml, len, ox_nomode_callbacks, 0, &options, err);
|
@@ -928,6 +930,7 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
928
930
|
* - *:symbolize_keys* [true|false|nil] symbolize element attribute keys or leave as Strings
|
929
931
|
* - *:invalid_replace* [nil|String] replacement string for invalid XML characters on dump. nil indicates include anyway as hex. A string, limited to 10 characters will replace the invalid character with the replace.
|
930
932
|
* - *:strip_namespace* [String|true|false] "" or false result in no namespace stripping. A string of "*" or true will strip all namespaces. Any other non-empty string indicates that matching namespaces will be stripped.
|
933
|
+
* - *:with_cdata* [true|false] if true cdata is included in hash_load output otherwise it is not.
|
931
934
|
*/
|
932
935
|
static VALUE
|
933
936
|
load_str(int argc, VALUE *argv, VALUE self) {
|
@@ -946,14 +949,8 @@ load_str(int argc, VALUE *argv, VALUE self) {
|
|
946
949
|
} else {
|
947
950
|
xml = ALLOCA_N(char, len);
|
948
951
|
}
|
949
|
-
#if
|
950
|
-
#ifdef MACRUBY_RUBY
|
951
|
-
encoding = rb_funcall(*argv, encoding_id, 0);
|
952
|
-
#else
|
952
|
+
#if HAVE_RB_OBJ_ENCODING
|
953
953
|
encoding = rb_obj_encoding(*argv);
|
954
|
-
#endif
|
955
|
-
#elif HAS_PRIVATE_ENCODING
|
956
|
-
encoding = rb_funcall(*argv, encoding_id, 0);
|
957
954
|
#else
|
958
955
|
encoding = Qnil;
|
959
956
|
#endif
|
@@ -1319,21 +1316,38 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
1319
1316
|
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
1320
1317
|
}
|
1321
1318
|
rstr = rb_str_new2(xml);
|
1322
|
-
#if
|
1319
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
1323
1320
|
if ('\0' != *copts.encoding) {
|
1324
1321
|
rb_enc_associate(rstr, rb_enc_find(copts.encoding));
|
1325
1322
|
}
|
1326
|
-
#elif HAS_PRIVATE_ENCODING
|
1327
|
-
if ('\0' != *copts.encoding) {
|
1328
|
-
rb_funcall(rstr, ox_force_encoding_id, 1, rb_str_new2(copts.encoding));
|
1329
|
-
}
|
1330
1323
|
#endif
|
1331
1324
|
xfree(xml);
|
1332
1325
|
|
1333
1326
|
return rstr;
|
1334
1327
|
}
|
1335
1328
|
|
1336
|
-
/* call-seq:
|
1329
|
+
/* call-seq: to_xml(obj, options) => xml-string
|
1330
|
+
*
|
1331
|
+
* Dumps an Object (obj) to a string.
|
1332
|
+
* - +obj+ [Object] Object to serialize as an XML document String
|
1333
|
+
* - +options+ [Hash] formating options
|
1334
|
+
* - *:indent* [Fixnum] format expected
|
1335
|
+
* - *:no_empty* [true|false] if true don't output empty elements
|
1336
|
+
* - *:xsd_date* [true|false] use XSD date format if true, default: false
|
1337
|
+
* - *:circular* [true|false] allow circular references, default: false
|
1338
|
+
* - *:strict|:tolerant]* [ :effort effort to use when an undumpable object (e.g., IO) is encountered, default: :strict
|
1339
|
+
* - _:strict_ - raise an NotImplementedError if an undumpable object is encountered
|
1340
|
+
* - _:tolerant_ - replaces undumplable objects with nil
|
1341
|
+
*
|
1342
|
+
* Note that an indent of less than zero will result in a tight one line output
|
1343
|
+
* unless the text in the XML fields contain new line characters.
|
1344
|
+
*/
|
1345
|
+
static VALUE
|
1346
|
+
to_xml(int argc, VALUE *argv, VALUE self) {
|
1347
|
+
return dump(argc, argv, self);
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
/* call-seq: to_file(file_path, obj, options) => Object
|
1337
1351
|
*
|
1338
1352
|
* Dumps an Object to the specified file.
|
1339
1353
|
* - +file_path+ [String] file path to write the XML document to
|
@@ -1392,7 +1406,7 @@ void Init_ox() {
|
|
1392
1406
|
rb_define_module_function(Ox, "sax_parse", sax_parse, -1);
|
1393
1407
|
rb_define_module_function(Ox, "sax_html", sax_html, -1);
|
1394
1408
|
|
1395
|
-
rb_define_module_function(Ox, "to_xml",
|
1409
|
+
rb_define_module_function(Ox, "to_xml", to_xml, -1);
|
1396
1410
|
rb_define_module_function(Ox, "dump", dump, -1);
|
1397
1411
|
|
1398
1412
|
rb_define_module_function(Ox, "load_file", load_file, -1);
|
@@ -1525,6 +1539,7 @@ void Init_ox() {
|
|
1525
1539
|
symbolize_sym = ID2SYM(rb_intern("symbolize")); rb_gc_register_address(&symbolize_sym);
|
1526
1540
|
tolerant_sym = ID2SYM(rb_intern("tolerant")); rb_gc_register_address(&tolerant_sym);
|
1527
1541
|
trace_sym = ID2SYM(rb_intern("trace")); rb_gc_register_address(&trace_sym);
|
1542
|
+
with_cdata_sym = ID2SYM(rb_intern("with_cdata")); rb_gc_register_address(&with_cdata_sym);
|
1528
1543
|
with_dtd_sym = ID2SYM(rb_intern("with_dtd")); rb_gc_register_address(&with_dtd_sym);
|
1529
1544
|
with_instruct_sym = ID2SYM(rb_intern("with_instructions")); rb_gc_register_address(&with_instruct_sym);
|
1530
1545
|
with_xml_sym = ID2SYM(rb_intern("with_xml")); rb_gc_register_address(&with_xml_sym);
|
@@ -1555,11 +1570,8 @@ void Init_ox() {
|
|
1555
1570
|
rb_define _module_function(Ox, "cache8_test", cache8_test, 0);
|
1556
1571
|
#endif
|
1557
1572
|
|
1558
|
-
#if
|
1573
|
+
#if HAVE_RB_ENC_FIND
|
1559
1574
|
ox_utf8_encoding = rb_enc_find("UTF-8");
|
1560
|
-
#elif HAS_PRIVATE_ENCODING
|
1561
|
-
ox_utf8_encoding = rb_str_new2("UTF-8");
|
1562
|
-
rb_gc_register_address(&ox_utf8_encoding);
|
1563
1575
|
#endif
|
1564
1576
|
}
|
1565
1577
|
|
@@ -1580,7 +1592,7 @@ _ox_raise_error(const char *msg, const char *xml, const char *current, const cha
|
|
1580
1592
|
xline++;
|
1581
1593
|
}
|
1582
1594
|
}
|
1583
|
-
#
|
1595
|
+
#ifdef RB_GC_GUARD
|
1584
1596
|
rb_gc_enable();
|
1585
1597
|
#endif
|
1586
1598
|
rb_raise(ox_parse_error_class, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
|