Skip to content

Commit

Permalink
Added :root option to tag method. This allows setting an object as th…
Browse files Browse the repository at this point in the history
…e root element, which sets xpath to use / and sets single to true for this object.
  • Loading branch information
jnunemaker committed Jan 29, 2009
1 parent a88ab23 commit 7ddc01d
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 34 deletions.
9 changes: 3 additions & 6 deletions examples/dashed_elements.rb
Expand Up @@ -7,8 +7,7 @@ module GitHub
class Commit
include HappyMapper

tag "commit"

tag "commit", :root => true
element :url, String
element :tree, String
element :message, String
Expand All @@ -17,7 +16,5 @@ class Commit
end
end

commits = GitHub::Commit.parse(file_contents)
commits.each do |commit|
puts commit.committed_date, commit.url, commit.id
end
commit = GitHub::Commit.parse(file_contents)
puts commit.committed_date, commit.url, commit.id
33 changes: 17 additions & 16 deletions lib/happymapper.rb
Expand Up @@ -51,22 +51,24 @@ def has_many(name, type, options={})
element name, type, {:single => false}.merge(options)
end

def tag(new_tag_name)
# Options:
# :root => Boolean, true means this is xml root
def tag(new_tag_name, o={})
options = {:root => false}.merge(o)
@root = options.delete(:root)
@tag_name = new_tag_name.to_s
end

def get_tag_name
@tag_name ||= to_s.downcase
end

def is_root?
@root
end

def parse(xml, o={})
options = {
:single => false,
:from_root => false,
}.merge(o)

xpath, collection = '', []

def parse(xml, o={})
xpath, collection, options = '', [], {:single => false}.merge(o)
doc = xml.is_a?(LibXML::XML::Node) ? xml : xml.to_libxml_doc
node = doc.respond_to?(:root) ? doc.root : doc

Expand All @@ -82,26 +84,25 @@ def parse(xml, o={})
namespace = node.namespaces.namespace.prefix + ":"
end

xpath += doc.respond_to?(:root) ? '' : '.'
xpath += options[:from_root] ? '/' : '//'
# xpath += doc.respond_to?(:root) ? '' : '.'
xpath += is_root? ? '/' : './/'
xpath += namespace if namespace
xpath += get_tag_name
# puts "parse: #{xpath}"

nodes = node.find(xpath)
nodes.each do |node|
nodes.each do |n|
obj = new

attributes.each do |attr|
obj.send("#{attr.method_name}=",
attr.from_xml_node(node))
attr.from_xml_node(n))
end

elements.each do |elem|
elem.namespace = namespace
# puts "#{elem.method_name} - #{namespace} - #{elem.namespace}"
obj.send("#{elem.method_name}=",
elem.from_xml_node(node))
elem.from_xml_node(n))
end
collection << obj
end
Expand All @@ -110,7 +111,7 @@ def parse(xml, o={})
nodes = nil
GC.start

options[:single] ? collection.first : collection
options[:single] || is_root? ? collection.first : collection
end
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/happymapper/item.rb
Expand Up @@ -33,7 +33,6 @@ def from_xml_node(node)
def xpath
xpath = ''
xpath += './/' if options[:deep]
# puts "xpath namespace: #{namespace}"
xpath += namespace if namespace
xpath += tag
# puts "xpath: #{xpath}"
Expand Down
7 changes: 7 additions & 0 deletions spec/fixtures/family_tree.xml
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<familytree xmlns="http://api.familysearch.org/familytree/v1" xmlns:fsapi-v1="http://api.familysearch.org/v1" version="1.0.20071213.942" statusMessage="OK" statusCode="200">
<persons>
<person version="1199378491000" modified="2008-01-03T09:41:31-07:00" id="KWQS-BBQ">
</person>
</persons>
</familytree>
61 changes: 50 additions & 11 deletions spec/happymapper_spec.rb
Expand Up @@ -21,6 +21,34 @@ class Product
has_one :feature_bullets, FeatureBullet
end

module FamilySearch
class Person
include HappyMapper

tag 'person'
attribute :version, String
attribute :modified, Time
attribute :id, String
end

class Persons
include HappyMapper

tag 'persons', :root => false
has_many :person, Person
end

class FamilyTree
include HappyMapper

tag 'familytree', :root => true
attribute :version, String
attribute :status_message, String, :tag => 'statusMessage'
attribute :status_code, String, :tag => 'statusCode'
has_one :persons, Persons
end
end

module FedEx
class Address
include HappyMapper
Expand Down Expand Up @@ -85,13 +113,13 @@ class TransactionDetail

class TrackReply
include HappyMapper

tag 'TrackReply'
tag 'TrackReply', :root => true
element :highest_severity, String, :tag => 'HighestSeverity'
has_many :notifications, Notification, :tag => 'Notifications'
has_one :tran_detail, TransactionDetail, :tab => 'TransactionDetail'
element :more_data, Boolean, :tag => 'MoreData'
has_many :notifications, Notification, :tag => 'Notifications'
has_many :trackdetails, TrackDetails, :tag => 'TrackDetails'
has_one :tran_detail, TransactionDetail, :tab => 'TransactionDetail'
end
end

Expand Down Expand Up @@ -156,6 +184,7 @@ class CurrentWeather
class Address
include HappyMapper

tag 'address', :root => true
element :street, String
element :postcode, String
element :housenumber, String
Expand Down Expand Up @@ -187,8 +216,7 @@ module GitHub
class Commit
include HappyMapper

tag "commit"

tag "commit", :root => true
element :url, String
element :tree, String
element :message, String
Expand Down Expand Up @@ -294,7 +322,7 @@ class Foo; include HappyMapper end
end

it "should parse xml attributes into ruby objects" do
posts = Post.parse(File.read(File.dirname(__FILE__) + '/fixtures/posts.xml'))
posts = Post.parse(fixture_file('posts.xml'))
posts.size.should == 20
first = posts.first
first.href.should == 'http://roxml.rubyforge.org/'
Expand All @@ -307,7 +335,7 @@ class Foo; include HappyMapper end
end

it "should parse xml elements to ruby objcts" do
statuses = Status.parse(File.read(File.dirname(__FILE__) + '/fixtures/statuses.xml'))
statuses = Status.parse(fixture_file('statuses.xml'))
statuses.size.should == 20
first = statuses.first
first.id.should == 882281424
Expand Down Expand Up @@ -374,7 +402,7 @@ class Foo; include HappyMapper end
end

it "should parse xml that has elements with dashes" do
commit = GitHub::Commit.parse(fixture_file('commit.xml')).first
commit = GitHub::Commit.parse(fixture_file('commit.xml'))
commit.message.should == "move commands.rb and helpers.rb into commands/ dir"
commit.url.should == "http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
commit.id.should == "c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
Expand Down Expand Up @@ -410,7 +438,7 @@ class Foo; include HappyMapper end
end

it "should parse xml with multiple namespaces" do
track = FedEx::TrackReply.parse(fixture_file('multiple_namespaces.xml'), :single => true, :from_root => true)
track = FedEx::TrackReply.parse(fixture_file('multiple_namespaces.xml'))
track.highest_severity.should == 'SUCCESS'
track.more_data.should be_false
notification = track.notifications.first
Expand Down Expand Up @@ -449,5 +477,16 @@ class Foo; include HappyMapper end
last_event.address.state.should == 'FL'
last_event.address.zip.should == '327506398'
track.tran_detail.cust_tran_id.should == '20090102-111321'
end
end

xit "should parse family search xml" do
tree = FamilySearch::FamilyTree.parse(fixture_file('family_tree.xml'))
tree.version.should == '1.0.20071213.942'
tree.status_message.should == 'OK'
tree.status_code.should == '200'
# tree.people.size.should == 1
# tree.people.first.version.should == '1199378491000'
# tree.people.first.modified.should == Time.utc(2008, 1, 3, 16, 41, 31) # 2008-01-03T09:41:31-07:00
# tree.people.first.id.should == 'KWQS-BBQ'
end
end

0 comments on commit 7ddc01d

Please sign in to comment.