ox 2.13.3 → 2.14.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4121ea0bb75760d8b57c9904bf884c44455e1d2613b3826b3765004b006c65a0
4
- data.tar.gz: cb5fbf251430612e4c46feca429a0b8d0e60fee8191a250ec540d709966ca20d
3
+ metadata.gz: 61328d1ef231a8c0ad2f7fad60e7d05e5ea04b61d524c092c889181d988e0fbd
4
+ data.tar.gz: d290d80bde79d99e9948b2d48ff53258cef7bc26651dac8a380fe1ee0aa2b05b
5
5
  SHA512:
6
- metadata.gz: 66995249fcc36e945629c09fe93bac6702b03e644d8fe310068f74f5dd1db47e65f98a86a7390f4cdefe865aa1976239caf283b393d725b1f6aae0cdc6a4d71c
7
- data.tar.gz: 447fa33cc0ac30e78e56823f83b1be8d09dedc7763cb0fb820366c20cfe86ce9aafd6649fd3d0bcc8f90885f60325dae756ec32b44786cd482f9f0f7fb98a7ca
6
+ metadata.gz: 436b12b1b9852b022c6425f1abeeb0aa74072d7ce7125b6dc6ef69e064cf287be7156a1a776282cb0db190fdda5098dc5da49ce40e2e7fa411eb700c50aecd2e
7
+ data.tar.gz: 6763e7b50c43db54cc4be1da5d59a4c8e7598ddbc4eeb496881c21442d14b21893fa90007340f99089282b4e8eb77a4fa9a54c57d15e5f163050fc2de7359b50
data/CHANGELOG.md CHANGED
@@ -2,7 +2,36 @@
2
2
 
3
3
  All changes to the Ox gem are documented here. Releases follow semantic versioning.
4
4
 
5
- ## [Unreleased]
5
+ ## [2.14.3] - 2021-03-22
6
+
7
+ ### Fixed
8
+
9
+ - Code issue around HAVE_RB_ENC_ASSOCIATE fixed.
10
+
11
+ ## [2.14.2] - 2021-03-07
12
+
13
+ ### Fixed
14
+
15
+ - Attribute keys for setting attributes no longer create seemily
16
+ duplicates if symbol and string keys are mixed.
17
+
18
+ ## [2.14.1] - 2021-01-11
19
+
20
+ ### Fixed
21
+
22
+ - In Ruby 3.0 Range objects are frozen. This version allows Ranges to be created on load.
23
+
24
+ ## [2.14.0] - 2020-12-15
25
+
26
+ ### Added
27
+
28
+ - The `:with_cdata` option added for the hash_load() function.
29
+
30
+ ## [2.13.4] - 2020-09-11
31
+
32
+ ### Fixed
33
+
34
+ - Fixed one crash that occurred when a corrupted object encoded string was provided.
6
35
 
7
36
  ## [2.13.3] - 2020-09-03
8
37
 
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # Ox gem
2
2
  A fast XML parser and Object marshaller as a Ruby gem.
3
3
 
4
- [![Build Status](https://secure.travis-ci.org/ohler55/ox.svg?branch=master)](http://travis-ci.org/ohler55/ox) [![TideLift](https://tidelift.com/badges/github/ohler55/ox)](https://tidelift.com/subscription/pkg/rubygems-ox?utm_source=rubygems-ox&utm_medium=referral&utm_campaign=readme)
5
- [![Financial Contributors on Open Collective](https://opencollective.com/ohler/all/badge.svg?label=financial+contributors)](https://opencollective.com/ohler)
4
+ [![Build status](https://ci.appveyor.com/api/projects/status/pg2w4wspbrflbi8c?svg=true)](https://ci.appveyor.com/project/ohler55/ox)
6
5
 
7
6
  ## Installation
8
7
  gem install ox
@@ -17,10 +16,6 @@ A fast XML parser and Object marshaller as a Ruby gem.
17
16
 
18
17
  *RubyGems* *repo*: https://rubygems.org/gems/ox
19
18
 
20
- ## Follow @oxgem on Twitter
21
-
22
- [Follow @peterohler on Twitter](http://twitter.com/#!/peterohler) for announcements and news about the Ox gem.
23
-
24
19
  ## Support
25
20
 
26
21
  [Get supported Ox with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-ox?utm_source=rubygems-ox&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
@@ -79,7 +74,7 @@ callbacks. Unlike Nokogiri and LibXML, Ox can be tuned to use only the SAX
79
74
  callbacks that are of interest to the caller. (See the perf_sax.rb file for an
80
75
  example.)
81
76
 
82
- Ox is compatible with Ruby 1.8.7, 1.9.3, 2.1.2, 2.2.0 and RBX.
77
+ Ox is compatible with Ruby 2.3, 2.4, 2.5, 2.6, 2.7, 3.0.
83
78
 
84
79
  ### Object Dump Sample:
85
80
 
data/ext/ox/dump.c CHANGED
@@ -838,7 +838,7 @@ dump_obj(ID aid, VALUE obj, int depth, Out out) {
838
838
  out->w_start(out, &e);
839
839
 
840
840
  for (i = 0; i < cnt; i++) {
841
- VALUE v = RSTRUCT_GET(obj, i);
841
+ VALUE v = RSTRUCT_GET(obj, (int)(i));
842
842
  dump_obj(rb_intern(ulong2str(i, num_buf + sizeof(num_buf) - 1)), v, d2, out);
843
843
  }
844
844
  out->w_end(out, &e);
data/ext/ox/gen_load.c CHANGED
@@ -116,18 +116,18 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
116
116
  #endif
117
117
  rb_hash_aset(ah, sym, rb_str_new2(attrs->value));
118
118
  } else {
119
+ #if HAVE_RB_ENC_ASSOCIATE
119
120
  volatile VALUE rstr = rb_str_new2(attrs->name);
120
121
 
121
- #if HAVE_RB_ENC_ASSOCIATE
122
122
  if (0 != pi->options->rb_enc) {
123
123
  rb_enc_associate(rstr, pi->options->rb_enc);
124
124
  }
125
125
  rb_hash_aset(ah, rstr, rb_str_new2(attrs->value));
126
- }
127
- if (0 == strcmp("encoding", attrs->name)) {
128
- pi->options->rb_enc = rb_enc_find(attrs->value);
129
- }
126
+ if (0 == strcmp("encoding", attrs->name)) {
127
+ pi->options->rb_enc = rb_enc_find(attrs->value);
128
+ }
130
129
  #endif
130
+ }
131
131
  }
132
132
  nodes = rb_ary_new();
133
133
  rb_ivar_set(doc, ox_attributes_id, ah);
data/ext/ox/hash_load.c CHANGED
@@ -74,9 +74,8 @@ unmark(PInfo pi, VALUE val) {
74
74
  }
75
75
 
76
76
  static void
77
- add_text(PInfo pi, char *text, int closed) {
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
81
  #if HAVE_RB_ENC_ASSOCIATE
@@ -102,6 +101,16 @@ add_text(PInfo pi, char *text, int closed) {
102
101
  }
103
102
  }
104
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
+
105
114
  static void
106
115
  add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
107
116
  if (helper_stack_empty(&pi->helpers)) {
@@ -250,6 +259,19 @@ struct _parseCallbacks _ox_hash_callbacks = {
250
259
 
251
260
  ParseCallbacks ox_hash_callbacks = &_ox_hash_callbacks;
252
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
+
253
275
  struct _parseCallbacks _ox_hash_no_attrs_callbacks = {
254
276
  NULL,
255
277
  NULL,
@@ -262,3 +284,16 @@ struct _parseCallbacks _ox_hash_no_attrs_callbacks = {
262
284
  };
263
285
 
264
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
@@ -42,10 +42,10 @@ static void fill_indent(PInfo pi, char *buf, size_t size);
42
42
 
43
43
 
44
44
  struct _parseCallbacks _ox_obj_callbacks = {
45
- instruct, /* instruct, */
46
- 0, /* add_doctype, */
47
- 0, /* add_comment, */
48
- 0, /* add_cdata, */
45
+ instruct, // instruct,
46
+ 0, // add_doctype,
47
+ 0, // add_comment,
48
+ 0, // add_cdata,
49
49
  add_text,
50
50
  add_element,
51
51
  end_element,
@@ -128,7 +128,7 @@ resolve_classname(VALUE mod, const char *class_name, Effort effort, VALUE base_c
128
128
  break;
129
129
  case StrictEffort:
130
130
  default:
131
- /* raise an error if name is not defined */
131
+ // raise an error if name is not defined
132
132
  clas = rb_const_get_at(mod, ci);
133
133
  break;
134
134
  }
@@ -183,7 +183,7 @@ parse_ulong(const char *s, PInfo pi) {
183
183
  return ULONG2NUM(n);
184
184
  }
185
185
 
186
- /* 2010-07-09T10:47:45.895826162+09:00 */
186
+ // 2010-07-09T10:47:45.895826162+09:00
187
187
  inline static VALUE
188
188
  parse_time(const char *text, VALUE clas) {
189
189
  VALUE t;
@@ -237,6 +237,7 @@ static ID
237
237
  get_var_sym_from_attrs(Attr a, void *encoding) {
238
238
  for (; 0 != a->name; a++) {
239
239
  if ('a' == *a->name && '\0' == *(a->name + 1)) {
240
+ name2var(a->value, encoding);
240
241
  return name2var(a->value, encoding);
241
242
  }
242
243
  }
@@ -558,7 +559,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
558
559
  printf("%s%s\n", indent, buf);
559
560
  }
560
561
  }
561
- if (helper_stack_empty(&pi->helpers)) { /* top level object */
562
+ if (helper_stack_empty(&pi->helpers)) { // top level object
562
563
  if (0 != (id = get_id_from_attrs(pi, attrs))) {
563
564
  pi->circ_array = circ_array_new();
564
565
  }
@@ -579,7 +580,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
579
580
  h->obj = Qfalse;
580
581
  break;
581
582
  case StringCode:
582
- /* h->obj will be replaced by add_text if it is called */
583
+ // h->obj will be replaced by add_text if it is called
583
584
  h->obj = ox_empty_string;
584
585
  if (0 != pi->circ_array) {
585
586
  pi->id = get_id_from_attrs(pi, attrs);
@@ -596,8 +597,8 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
596
597
  case ComplexCode:
597
598
  case DateCode:
598
599
  case TimeCode:
599
- case RationalCode: /* sub elements read next */
600
- /* value will be read in the following add_text */
600
+ case RationalCode: // sub elements read next
601
+ // value will be read in the following add_text
601
602
  h->obj = Qundef;
602
603
  break;
603
604
  case String64Code:
@@ -619,7 +620,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
619
620
  }
620
621
  break;
621
622
  case RangeCode:
622
- h->obj = rb_range_new(ox_zero_fixnum, ox_zero_fixnum, Qfalse);
623
+ h->obj = rb_ary_new_from_args(3, Qnil, Qnil, Qfalse);
623
624
  break;
624
625
  case RawCode:
625
626
  if (hasChildren) {
@@ -699,12 +700,15 @@ end_element(PInfo pi, const char *ename) {
699
700
  Helper ph = helper_stack_peek(&pi->helpers);
700
701
 
701
702
  if (ox_empty_string == h->obj) {
702
- /* special catch for empty strings */
703
+ // special catch for empty strings
703
704
  h->obj = rb_str_new2("");
704
- }
705
- if (Qundef == h->obj) {
705
+ } else if (Qundef == h->obj) {
706
706
  set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
707
707
  return;
708
+ } else if (RangeCode == h->type) { // Expect an array of 3 elements.
709
+ const VALUE *ap = RARRAY_PTR(h->obj);
710
+
711
+ h->obj = rb_range_new(*ap, *(ap + 1), Qtrue == *(ap + 2));
708
712
  }
709
713
  pi->obj = h->obj;
710
714
  if (0 != ph) {
@@ -715,10 +719,14 @@ end_element(PInfo pi, const char *ename) {
715
719
  case ExceptionCode:
716
720
  case ObjectCode:
717
721
  if (Qnil != ph->obj) {
718
- if (0 == h->var) {
722
+ if (0 == h->var || NULL == rb_id2name(h->var )) {
719
723
  set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
720
724
  return;
721
725
  }
726
+ if (RUBY_T_OBJECT != rb_type(ph->obj)) {
727
+ set_error(&pi->err, "Corrupt object encoding", pi->str, pi->s);
728
+ return;
729
+ }
722
730
  rb_ivar_set(ph->obj, h->var, h->obj);
723
731
  }
724
732
  break;
@@ -735,11 +743,11 @@ end_element(PInfo pi, const char *ename) {
735
743
  break;
736
744
  case RangeCode:
737
745
  if (ox_beg_id == h->var) {
738
- RSTRUCT_SET(ph->obj, 0, h->obj);
746
+ rb_ary_store(ph->obj, 0, h->obj);
739
747
  } else if (ox_end_id == h->var) {
740
- RSTRUCT_SET(ph->obj, 1, h->obj);
748
+ rb_ary_store(ph->obj, 1, h->obj);
741
749
  } else if (ox_excl_id == h->var) {
742
- RSTRUCT_SET(ph->obj, 2, h->obj);
750
+ rb_ary_store(ph->obj, 2, h->obj);
743
751
  } else {
744
752
  set_error(&pi->err, "Invalid range attribute", pi->str, pi->s);
745
753
  return;
@@ -898,7 +906,7 @@ parse_xsd_time(const char *text, VALUE clas) {
898
906
  #endif
899
907
  }
900
908
 
901
- /* debug functions */
909
+ // debug functions
902
910
  static void
903
911
  fill_indent(PInfo pi, char *buf, size_t size) {
904
912
  size_t cnt;
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;
@@ -179,6 +180,7 @@ struct _options ox_default_options = {
179
180
  true, // convert_special
180
181
  No, // allow_invalid
181
182
  false, // no_empty
183
+ false, // with_cdata
182
184
  { '\0' }, // inv_repl
183
185
  { '\0' }, // strip_ns
184
186
  NULL, // html_hints
@@ -192,7 +194,9 @@ extern ParseCallbacks ox_gen_callbacks;
192
194
  extern ParseCallbacks ox_limited_callbacks;
193
195
  extern ParseCallbacks ox_nomode_callbacks;
194
196
  extern ParseCallbacks ox_hash_callbacks;
197
+ extern ParseCallbacks ox_hash_cdata_callbacks;
195
198
  extern ParseCallbacks ox_hash_no_attrs_callbacks;
199
+ extern ParseCallbacks ox_hash_no_attrs_cdata_callbacks;
196
200
 
197
201
  static void parse_dump_options(VALUE ropts, Options copts);
198
202
 
@@ -290,6 +294,7 @@ hints_to_overlay(Hints hints) {
290
294
  * - _:convert_special_ [true|false|nil] flag indicating special characters like &lt; are converted with the SAX parser
291
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.
292
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
293
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.
294
299
  * - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
295
300
  * - _:active_ - make the normal callback for the element
@@ -324,6 +329,7 @@ get_def_opts(VALUE self) {
324
329
  rb_hash_aset(opts, smart_sym, (Yes == ox_default_options.smart) ? Qtrue : ((No == ox_default_options.smart) ? Qfalse : Qnil));
325
330
  rb_hash_aset(opts, convert_special_sym, (ox_default_options.convert_special) ? Qtrue : Qfalse);
326
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);
327
333
  switch (ox_default_options.mode) {
328
334
  case ObjMode: rb_hash_aset(opts, mode_sym, object_sym); break;
329
335
  case GenMode: rb_hash_aset(opts, mode_sym, generic_sym); break;
@@ -431,6 +437,7 @@ sax_html_overlay(VALUE self) {
431
437
  * - _:smart_ [true|false|nil] flag indicating the SAX parser uses hints if available (use with html)
432
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.
433
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
434
441
  * - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
435
442
  * - _:active_ - make the normal callback for the element
436
443
  * - _:nest_ok_ - active but ignore nest check
@@ -630,6 +637,10 @@ set_def_opts(VALUE self, VALUE opts) {
630
637
  rb_hash_foreach(v, set_overlay, (VALUE)ox_default_options.html_hints);
631
638
  }
632
639
  }
640
+ if (Qnil != (v = rb_hash_lookup(opts, with_cdata_sym))) {
641
+ ox_default_options.with_cdata = (Qtrue == v);
642
+ }
643
+
633
644
  ox_default_options.element_key_mod = rb_hash_lookup2(opts, element_key_mod_sym, ox_default_options.element_key_mod);
634
645
  ox_default_options.attr_key_mod = rb_hash_lookup2(opts, attr_key_mod_sym, ox_default_options.attr_key_mod);
635
646
 
@@ -838,6 +849,9 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
838
849
  options.margin[sizeof(options.margin) - 1] = '\0';
839
850
  options.margin_len = strlen(options.margin);
840
851
  }
852
+ if (Qnil != (v = rb_hash_lookup(h, with_cdata_sym))) {
853
+ options.with_cdata = (Qtrue == v);
854
+ }
841
855
  }
842
856
  #if HAVE_RB_ENC_FIND
843
857
  if ('\0' == *options.encoding) {
@@ -869,10 +883,18 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
869
883
  obj = ox_parse(xml, len, ox_limited_callbacks, 0, &options, err);
870
884
  break;
871
885
  case HashMode:
872
- obj = ox_parse(xml, len, ox_hash_callbacks, 0, &options, err);
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
+ }
873
891
  break;
874
892
  case HashNoAttrMode:
875
- obj = ox_parse(xml, len, ox_hash_no_attrs_callbacks, 0, &options, err);
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
+ }
876
898
  break;
877
899
  case NoMode:
878
900
  obj = ox_parse(xml, len, ox_nomode_callbacks, 0, &options, err);
@@ -908,6 +930,7 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
908
930
  * - *:symbolize_keys* [true|false|nil] symbolize element attribute keys or leave as Strings
909
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.
910
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.
911
934
  */
912
935
  static VALUE
913
936
  load_str(int argc, VALUE *argv, VALUE self) {
@@ -1516,6 +1539,7 @@ void Init_ox() {
1516
1539
  symbolize_sym = ID2SYM(rb_intern("symbolize")); rb_gc_register_address(&symbolize_sym);
1517
1540
  tolerant_sym = ID2SYM(rb_intern("tolerant")); rb_gc_register_address(&tolerant_sym);
1518
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);
1519
1543
  with_dtd_sym = ID2SYM(rb_intern("with_dtd")); rb_gc_register_address(&with_dtd_sym);
1520
1544
  with_instruct_sym = ID2SYM(rb_intern("with_instructions")); rb_gc_register_address(&with_instruct_sym);
1521
1545
  with_xml_sym = ID2SYM(rb_intern("with_xml")); rb_gc_register_address(&with_xml_sym);
data/ext/ox/ox.h CHANGED
@@ -136,6 +136,7 @@ typedef struct _options {
136
136
  char convert_special;// boolean true or false
137
137
  char allow_invalid; // YesNo
138
138
  char no_empty; // boolean - no empty elements when dumping
139
+ char with_cdata; // boolean - hash_load should include cdata
139
140
  char inv_repl[12]; // max 10 valid characters, first character is the length
140
141
  char strip_ns[64]; // namespace to strip, \0 is no-strip, \* is all, else only matches
141
142
  struct _hints *html_hints; // html hints
data/lib/ox/element.rb CHANGED
@@ -115,17 +115,8 @@ module Ox
115
115
  # matching name will be yielded to. If the cond is a Hash then the
116
116
  # keys-value pairs in the cond must match the child attribute values with
117
117
  # the same keys. Any other cond type will yield to nothing.
118
- def each(cond=nil)
119
- if cond.nil?
120
- nodes.each { |n| yield(n) }
121
- else
122
- cond = cond.to_s if cond.is_a?(Symbol)
123
- if cond.is_a?(String)
124
- nodes.each { |n| yield(n) if n.is_a?(Element) && cond == n.name }
125
- elsif cond.is_a?(Hash)
126
- nodes.each { |n| yield(n) if n.is_a?(Element) && n.attr_match(cond) }
127
- end
128
- end
118
+ def each(cond=nil, &block)
119
+ build_enumerator(cond).each(&block)
129
120
  end
130
121
 
131
122
  # Returns an array of Nodes or Strings that correspond to the locations
@@ -413,6 +404,24 @@ module Ox
413
404
 
414
405
  private
415
406
 
407
+ # Builds an enumerator for use in `#each` call
408
+ #
409
+ # - +cond+ [Hash, String, nil] an element filter
410
+ def build_enumerator(cond)
411
+ if cond.nil?
412
+ nodes.each
413
+ else
414
+ cond = cond.to_s if cond.is_a?(Symbol)
415
+ Enumerator.new do |yielder|
416
+ if cond.is_a?(String)
417
+ nodes.each { |n| yielder.yield(n) if n.is_a?(Element) && cond == n.name }
418
+ elsif cond.is_a?(Hash)
419
+ nodes.each { |n| yielder.yield(n) if n.is_a?(Element) && n.attr_match(cond) }
420
+ end
421
+ end
422
+ end
423
+ end
424
+
416
425
  # Removes recursively children for nodes and sub_nodes
417
426
  #
418
427
  # - +found+ [Array] An array of Ox::Element
data/lib/ox/hasattrs.rb CHANGED
@@ -13,7 +13,7 @@ module Ox
13
13
  @attributes = { } if !instance_variable_defined?(:@attributes) or @attributes.nil?
14
14
  @attributes
15
15
  end
16
-
16
+
17
17
  # Returns the value of an attribute.
18
18
  # - +attr+ [Symbol|String] attribute name or key to return the value for
19
19
  def [](attr)
@@ -27,9 +27,16 @@ module Ox
27
27
  def []=(attr, value)
28
28
  raise "argument to [] must be a Symbol or a String." unless attr.is_a?(Symbol) or attr.is_a?(String)
29
29
  @attributes = { } if !instance_variable_defined?(:@attributes) or @attributes.nil?
30
+ a_str = attr.to_s
31
+ a_sym = attr.to_sym
32
+ if @attributes.has_key?(a_str)
33
+ attr = a_str
34
+ elsif @attributes.has_key?(a_sym)
35
+ attr = a_sym
36
+ end
30
37
  @attributes[attr] = value.to_s
31
38
  end
32
-
39
+
33
40
  # Handles the 'easy' API that allows navigating a simple XML by
34
41
  # referencing attributes by name.
35
42
  # - +id+ [Symbol] element or attribute name
data/lib/ox/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Ox
3
3
  # Current version of the module.
4
- VERSION = '2.13.3'
4
+ VERSION = '2.14.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ox
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.3
4
+ version: 2.14.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-03 00:00:00.000000000 Z
11
+ date: 2021-03-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
14
14
  XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
@@ -76,7 +76,7 @@ homepage: http://www.ohler.com/ox
76
76
  licenses:
77
77
  - MIT
78
78
  metadata: {}
79
- post_install_message:
79
+ post_install_message:
80
80
  rdoc_options:
81
81
  - "--main"
82
82
  - README.md
@@ -98,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
100
  requirements: []
101
- rubygems_version: 3.1.2
102
- signing_key:
101
+ rubygems_version: 3.2.3
102
+ signing_key:
103
103
  specification_version: 4
104
104
  summary: A fast XML parser and object serializer.
105
105
  test_files: []