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)