@@ -85,15 +85,23 @@ def self.xml_to_hash(node, hash = {}, opts = {})
8585 name = node . name
8686 schema = opts [ :schema ]
8787 opts [ :typecast_cache ] ||= { }
88+ opts [ :is_repetitive_cache ] ||= { }
8889
8990 # Insert node hash into parent hash correctly.
9091 case hash [ name ]
9192 when Array
9293 hash [ name ] << node_hash
9394 when Hash , String
95+ # This parent has multiple nodes with the same name, but when we checked the first time,
96+ # we found it is not defined as repetitive. I guess this means the schema is a liar.
9497 hash [ name ] = [ hash [ name ] , node_hash ]
9598 else
96- hash [ name ] = node_hash
99+ # We didn't see this node name under this parent yet.
100+ if is_repetitive? ( schema , node . path , opts [ :is_repetitive_cache ] )
101+ hash [ name ] = [ node_hash ]
102+ else
103+ hash [ name ] = node_hash
104+ end
97105 end
98106
99107 # Handle child elements
@@ -142,6 +150,21 @@ def self.typecast(schema, xpath, value, typecast_cache)
142150 type_proc [ value ]
143151 end
144152
153+ # Determines if the node is repetitive. Just because something is repetitive doesn't mean it always repeats.
154+ # For example, a customer query could return 1 result or 100, but in both cases, we should be returning an
155+ # Array.
156+ def self . is_repetitive? ( schema , xpath , is_repetitive_cache )
157+ # Yes, we are parsing comments.
158+ comment_path = xpath . gsub ( /\[ \d +\] / , '' ) + "/comment()"
159+ return is_repetitive_cache [ comment_path ] || parse_repetitive_from_comment ( schema , comment_path )
160+ end
161+
162+ def self . parse_repetitive_from_comment ( schema , comment_path )
163+ comment = schema . xpath ( comment_path ) . first
164+ return false if comment . nil?
165+ return comment . text . include? ( 'may rep' )
166+ end
167+
145168 def self . deep_convert ( hash , opts = { } , &block )
146169 hash . inject ( self . new ) do |h , ( k , v ) |
147170 k = k . to_s
0 commit comments