class Stockboy::Readers::XML

Extract data from XML

This works great with SOAP, probably not fully-featured yet for various XML formats. The SOAP provider returns a hash, because it takes care of extracting the envelope body already, so this reader supports options for reading elements from a nested hash too.

Backed by the Nori gem from Savon, see nori for full options.

Public Class Methods

new(opts={}, &block) click to toggle source

Initialize a new XML reader

Calls superclass method Stockboy::Reader::new
# File lib/stockboy/readers/xml.rb, line 86
def initialize(opts={}, &block)
  super
  self.elements = opts.delete(:elements)
  @xml_options = opts
  DSL.new(self).instance_eval(&block) if block_given?
end

Public Instance Methods

elements() click to toggle source
# File lib/stockboy/readers/xml.rb, line 72
def elements
  convert_tags_to ? @elements.map(&convert_tags_to) : @elements
end
elements=(schema) click to toggle source
# File lib/stockboy/readers/xml.rb, line 76
def elements=(schema)
  return @elements = [] unless schema
  raise(ArgumentError, "expected an array of XML tag strings") unless schema.is_a? Array
  @elements = schema.map(&:to_s)
end
options() click to toggle source

XML options passed to the underlying Nori instance

@!attribute [r] options @return [Hash]

# File lib/stockboy/readers/xml.rb, line 98
def options
  @xml_options
end
parse(data) click to toggle source
# File lib/stockboy/readers/xml.rb, line 102
def parse(data)
  hash = if data.is_a? Hash
    data
  else
    if data.respond_to? :to_xml
      data.to_xml("UTF-8")
      nori.parse(data)
    elsif data.respond_to? :to_hash
      data.to_hash
    else
      data.encode!("UTF-8", encoding) if encoding
      nori.parse(data)
    end
  end

  with_string_pool do
    remap_keys hash
    extract hash
  end
end

Private Instance Methods

extract(hash) click to toggle source
# File lib/stockboy/readers/xml.rb, line 129
def extract(hash)
  result = elements.inject hash do |memo, key|
    return [] if memo[key].nil?
    memo[key]
  end

  result = [result] unless result.is_a? Array
  result.compact!
  result
end
nori() click to toggle source
# File lib/stockboy/readers/xml.rb, line 125
def nori
  @nori ||= Nori.new(options)
end
remap_keys(node) click to toggle source
# File lib/stockboy/readers/xml.rb, line 140
def remap_keys(node)
  mapper = convert_tags_to || ->(tag) { tag }
  case node
  when Hash
    node.keys.each do |k|
      tag = string_pool(mapper.call(k))
      node[tag] = remap_keys(node.delete(k))
    end
  when Array
    node.each { |value| remap_keys(value) }
  end
  node
end