diff --git a/lib/qbxml/hash.rb b/lib/qbxml/hash.rb
index 0b47427..89ecf0a 100644
--- a/lib/qbxml/hash.rb
+++ b/lib/qbxml/hash.rb
@@ -85,15 +85,23 @@ def self.xml_to_hash(node, hash = {}, opts = {})
name = node.name
schema = opts[:schema]
opts[:typecast_cache] ||= {}
+ opts[:is_repetitive_cache] ||= {}
# Insert node hash into parent hash correctly.
case hash[name]
when Array
hash[name] << node_hash
when Hash, String
+ # This parent has multiple nodes with the same name, but when we checked the first time,
+ # we found it is not defined as repetitive. I guess this means the schema is a liar.
hash[name] = [hash[name], node_hash]
else
- hash[name] = node_hash
+ # We didn't see this node name under this parent yet.
+ if is_repetitive?(schema, node.path, opts[:is_repetitive_cache])
+ hash[name] = [node_hash]
+ else
+ hash[name] = node_hash
+ end
end
# Handle child elements
@@ -142,6 +150,21 @@ def self.typecast(schema, xpath, value, typecast_cache)
type_proc[value]
end
+ # Determines if the node is repetitive. Just because something is repetitive doesn't mean it always repeats.
+ # For example, a customer query could return 1 result or 100, but in both cases, we should be returning an
+ # Array.
+ def self.is_repetitive?(schema, xpath, is_repetitive_cache)
+ # Yes, we are parsing comments.
+ comment_path = xpath.gsub(/\[\d+\]/,'') + "/comment()"
+ return is_repetitive_cache[comment_path] || parse_repetitive_from_comment(schema, comment_path)
+ end
+
+ def self.parse_repetitive_from_comment(schema, comment_path)
+ comment = schema.xpath(comment_path).first
+ return false if comment.nil?
+ return comment.text.include?('may rep')
+ end
+
def self.deep_convert(hash, opts = {}, &block)
hash.inject(self.new) do |h, (k,v)|
k = k.to_s
diff --git a/test/unit/xml_to_hash_test.rb b/test/unit/xml_to_hash_test.rb
index 1828438..7dbdbad 100644
--- a/test/unit/xml_to_hash_test.rb
+++ b/test/unit/xml_to_hash_test.rb
@@ -26,9 +26,28 @@ def test_array_of_strings
assert_equal h, qbxml.from_qbxml("\n\n \n \n TxnID\n RefNumber\n \n \n\n")
end
- def test_float_percentage
+ def test_array_with_one_element
qbxml = Qbxml.new
+ h = {
+ "qbxml" => {
+ "xml_attributes" => {},
+ "qbxml_msgs_rs" => {
+ "xml_attributes" => {},
+ 'customer_query_rs' => {
+ "xml_attributes" => {},
+ 'customer_ret' => [{
+ "xml_attributes"=> {},
+ 'list_id' => 'abc'
+ }]
+ }
+ }
+ }
+ }
+ assert_equal h, qbxml.from_qbxml("\n\n \n \n abc\n \n \n\n")
+ end
+ def test_float_percentage
+ qbxml = Qbxml.new
h = {
"qbxml" => {
"xml_attributes" => {},