@@ -85,15 +85,23 @@ def self.xml_to_hash(node, hash = {}, opts = {})
85
85
name = node . name
86
86
schema = opts [ :schema ]
87
87
opts [ :typecast_cache ] ||= { }
88
+ opts [ :is_repetitive_cache ] ||= { }
88
89
89
90
# Insert node hash into parent hash correctly.
90
91
case hash [ name ]
91
92
when Array
92
93
hash [ name ] << node_hash
93
94
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.
94
97
hash [ name ] = [ hash [ name ] , node_hash ]
95
98
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
97
105
end
98
106
99
107
# Handle child elements
@@ -142,6 +150,21 @@ def self.typecast(schema, xpath, value, typecast_cache)
142
150
type_proc [ value ]
143
151
end
144
152
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
+
145
168
def self . deep_convert ( hash , opts = { } , &block )
146
169
hash . inject ( self . new ) do |h , ( k , v ) |
147
170
k = k . to_s
0 commit comments