lib/qbxml/hash.rb in qbxml-0.1.6 vs lib/qbxml/hash.rb in qbxml-0.2.0

- old
+ new

@@ -43,18 +43,17 @@ def self.hash_to_xml(hash, opts = {}) opts = opts.dup opts[:indent] ||= 2 opts[:root] ||= :hash opts[:attributes] ||= (hash.delete(ATTR_ROOT) || {}) - opts[:xml_directive] ||= [:xml, {}] opts[:builder] ||= Builder::XmlMarkup.new(indent: opts[:indent]) opts[:skip_types] = true unless opts.key?(:skip_types) opts[:skip_instruct] = false unless opts.key?(:skip_instruct) builder = opts[:builder] unless opts.delete(:skip_instruct) - builder.instruct!(opts[:xml_directive].first, opts[:xml_directive].last) + builder.instruct!(opts[:schema], version: opts[:version]) end builder.tag!(opts[:root], opts.delete(:attributes)) do hash.each do |key, val| case val @@ -73,10 +72,11 @@ def self.xml_to_hash(node, hash = {}, opts = {}) node_hash = {CONTENT_ROOT => '', ATTR_ROOT => {}} name = node.name schema = opts[:schema] + opts[:typecast_cache] ||= {} # Insert node hash into parent hash correctly. case hash[name] when Array then hash[name] << node_hash when Hash then hash[name] = [hash[name], node_hash] @@ -103,11 +103,11 @@ node_hash.delete(CONTENT_ROOT) elsif node_hash[CONTENT_ROOT].present? node_hash.delete(ATTR_ROOT) hash[name] = \ if schema - typecast(schema, node.path, node_hash[CONTENT_ROOT]) + typecast(schema, node.path, node_hash[CONTENT_ROOT], opts[:typecast_cache]) else node_hash[CONTENT_ROOT] end else hash[name] = node_hash[CONTENT_ROOT] @@ -117,12 +117,13 @@ end private - def self.typecast(schema, xpath, value) + def self.typecast(schema, xpath, value, typecast_cache) type_path = xpath.gsub(/\[\d+\]/,'') - type_proc = Qbxml::TYPE_MAP[schema.xpath(type_path).first.try(:text)] + # This is fairly expensive. Cache it for better performance when parsing lots of records of the same type. + type_proc = typecast_cache[type_path] ||= Qbxml::TYPE_MAP[schema.xpath(type_path).first.try(:text)] raise "#{xpath} is not a valid type" unless type_proc type_proc[value] end def self.deep_convert(hash, opts = {}, &block)