class Praxis::Handlers::XML

Public Class Methods

new() click to toggle source

Construct an XML handler and initialize any related libraries.

@raise [Praxis::Exceptions::InvalidConfiguration] if the handler is unsupported

# File lib/praxis/handlers/xml_sample.rb, line 15
def initialize
  require 'nokogiri'
  require 'builder'
  require 'active_support'
  ActiveSupport::XmlMini.backend = 'Nokogiri'
rescue LoadError
  raise Praxis::Exceptions::InvalidConfiguration,
        'XML handler depends on builder ~> 3.2 and nokogiri ~> 1.6; please add them to your Gemfile'
end

Public Instance Methods

generate(structured_data) click to toggle source

Generate a pretty-printed XML document from structured data.

@param [Hash,Array] structured_data @return [String]

# File lib/praxis/handlers/xml_sample.rb, line 38
def generate(structured_data)
  # courtesy of active_support + builder
  structured_data.to_xml
end
parse(document) click to toggle source

Parse an XML document into structured data.

@param [String] document @return [Hash,Array] the structured-data representation of the document

# File lib/praxis/handlers/xml_sample.rb, line 29
def parse(document)
  p = Nokogiri::XML(document)
  process(p.root, p.root.attributes['type'])
end

Protected Instance Methods

process(node, type_attribute) click to toggle source

Transform a Nokogiri DOM object into structured data.

# File lib/praxis/handlers/xml_sample.rb, line 46
def process(node, type_attribute)
  type = type_attribute.value if type_attribute

  case type
  when nil
    if (node.children.size == 1 && node.child.text?) || node.children.empty?
      # leaf text node
      node.content
    else
      # A hash
      node.children.each_with_object({}) do |child, hash|
        next unless child.element? # There might be text fragments like newlines...spaces

        hash[child.name.underscore] = process(child, child.attributes['type'])
      end
    end
  when 'array'
    node.children.each_with_object([]) do |child, arr|
      next unless child.element? # There might be text fragments like newlines...spaces

      arr << process(child, child.attributes['type'])
    end
  when 'integer'
    Integer(node.content)
  when 'symbol'
    node.content.to_sym
  when 'decimal'
    BigDecimal(node.content)
  when 'float'
    Float(node.content)
  when 'boolean'
    node.content != 'false'
  when 'date'
    Date.parse(node.content)
  when 'dateTime'
    DateTime.parse(node.content)
  else
    raise ArgumentError, "Unknown attribute type: #{type}"
  end
end