Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Module to be used with Her ORM to parse XML REST API. Specifically for Redmine REST feed.

View redmine.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
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
Something went wrong with that request. Please try again.