Skip to content

Commit f91b0ba

Browse files
authored
Merge pull request #21 from qbwc/single-element-array
Use consistent types in xml_to_hash #17
2 parents f93d594 + 6df91c1 commit f91b0ba

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

lib/qbxml/hash.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

test/unit/xml_to_hash_test.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,28 @@ def test_array_of_strings
2626
assert_equal h, qbxml.from_qbxml("<?qbxml version=\"7.0\"?>\n<QBXML>\n <QBXMLMsgsRq>\n <InvoiceQueryRq>\n <IncludeRetElement>TxnID</IncludeRetElement>\n <IncludeRetElement>RefNumber</IncludeRetElement>\n </InvoiceQueryRq>\n </QBXMLMsgsRq>\n</QBXML>\n")
2727
end
2828

29-
def test_float_percentage
29+
def test_array_with_one_element
3030
qbxml = Qbxml.new
31+
h = {
32+
"qbxml" => {
33+
"xml_attributes" => {},
34+
"qbxml_msgs_rs" => {
35+
"xml_attributes" => {},
36+
'customer_query_rs' => {
37+
"xml_attributes" => {},
38+
'customer_ret' => [{
39+
"xml_attributes"=> {},
40+
'list_id' => 'abc'
41+
}]
42+
}
43+
}
44+
}
45+
}
46+
assert_equal h, qbxml.from_qbxml("<?qbxml version=\"7.0\"?>\n<QBXML>\n <QBXMLMsgsRs>\n <CustomerQueryRs>\n <CustomerRet><ListID>abc</ListID></CustomerRet>\n </CustomerQueryRs>\n </QBXMLMsgsRs>\n</QBXML>\n")
47+
end
3148

49+
def test_float_percentage
50+
qbxml = Qbxml.new
3251
h = {
3352
"qbxml" => {
3453
"xml_attributes" => {},

0 commit comments

Comments
 (0)