Created
October 12, 2012 14:20
-
-
Save mccannf/3879418 to your computer and use it in GitHub Desktop.
Module to be used with Her ORM to parse XML REST API. Specifically for Redmine REST feed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Redmine | |
class Issue | |
include Her::Model | |
end | |
class ParseXML < Faraday::Response::Middleware | |
# Parse the response body | |
# | |
# @param [String] body The response body | |
# @return [Mixed] the parsed response | |
def parse(body) # {{{ | |
xml = Redmine::Hash.from_xml(body) | |
errors = xml.delete(:errors) || [] | |
metadata = xml.delete(:metadata) || [] | |
{ | |
:data => xml, | |
:errors => errors, | |
:metadata => metadata | |
} | |
end # }}} | |
# This method is triggered when the response has been received. It modifies | |
# the value of `env[:body]`. | |
# | |
# @param [Hash] env The response environment | |
def on_complete(env) # {{{ | |
env[:body] = parse(env[:body]) | |
end # }}} | |
end | |
# USAGE: Hash.from_xml:(YOUR_XML_STRING) | |
# Taken from https://gist.github.com/335286 | |
require 'nokogiri' | |
# modified from http://stackoverflow.com/questions/1230741/convert-a-nokogiri-document-to-a-ruby-hash/1231297#1231297 | |
class Hash | |
class << self | |
def from_xml(xml_io) | |
begin | |
result = Nokogiri::XML(xml_io) | |
return { result.root.name.to_sym => xml_node_to_hash(result.root)} | |
rescue Exception => e | |
# raise your custom exception here | |
end | |
end | |
def xml_node_to_hash(node) | |
# If we are at the root of the document, start the hash | |
if node.element? | |
result_hash = {} | |
if node.attributes != {} | |
result_hash[:attributes] = {} | |
node.attributes.keys.each do |key| | |
result_hash[:attributes][node.attributes[key].name.to_sym] = prepare(node.attributes[key].value) | |
end | |
end | |
if node.children.size > 0 | |
node.children.each do |child| | |
result = xml_node_to_hash(child) | |
if child.name == "text" | |
unless child.next_sibling || child.previous_sibling | |
if result_hash[:attributes] | |
result_hash['value'] = prepare(result) | |
return result_hash | |
else | |
return prepare(result) | |
end | |
end | |
elsif result_hash[child.name.to_sym] | |
if result_hash[child.name.to_sym].is_a?(Object::Array) | |
result_hash[child.name.to_sym] << prepare(result) | |
else | |
result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << prepare(result) | |
end | |
else | |
result_hash[child.name.to_sym] = prepare(result) | |
end | |
end | |
return result_hash | |
else | |
return result_hash | |
end | |
else | |
return prepare(node.content.to_s) | |
end | |
end | |
def prepare(data) | |
(data.class == String && data.to_i.to_s == data) ? data.to_i : data | |
end | |
end | |
def to_struct(struct_name) | |
Struct.new(struct_name,*keys).new(*values) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment