lzell-mapricot 0.0.1 → 0.0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
1
  == 0.0.1 2009-03-06
2
2
 
3
- First gem!
3
+ First gem!
4
+
5
+ == 0.0.2 2009-03-17
6
+
7
+ Nokogiri and Libxml support.
8
+
9
+ Select the parser to use by setting Mapricot.parser as follows:
10
+
11
+ Mapricot.parser = :nokogiri
12
+ Mapricot.parser = :libxml
13
+ Mapricot.parser = :hpricot
14
+
15
+ Hpricot will be used by default
data/README.rdoc CHANGED
@@ -5,7 +5,7 @@ Makes working with XML stupid easy. XML to object mapper with an interface simi
5
5
 
6
6
  == Install
7
7
 
8
- Do some stuff...
8
+ sudo gem install lzell-mapricot
9
9
 
10
10
  == Usage
11
11
 
@@ -20,16 +20,15 @@ When you instantiate a Mapricot::Base object, you can pass it a string of xml:
20
20
 
21
21
  MapMe.new :xml => "<some_stuff>...</some_stuff>"
22
22
 
23
- Or you can pass it a url:
24
- class MapMeToo < Mapricot::Base
25
- end
23
+ Or a url:
26
24
 
27
- MapMeToo.new :url => "http://some_url"
25
+ MapMe.new :url => "http://some_url"
28
26
 
29
27
  == Examples
30
28
 
31
29
  ==== Super Simple
32
-
30
+ require 'mapricot'
31
+
33
32
  simple_xml = %(
34
33
  <user>
35
34
  <id>1</name>
@@ -54,7 +53,8 @@ Or you can pass it a url:
54
53
 
55
54
 
56
55
  ==== A little more realistic
57
-
56
+ require 'mapricot'
57
+
58
58
  xml = %(
59
59
  <user>
60
60
  <id>2</name>
@@ -110,9 +110,10 @@ Or you can pass it a url:
110
110
  # => Skiing for 2 years
111
111
  # => Hiking for 3 years
112
112
 
113
+
113
114
  == Credits
114
115
 
115
- All to why the luck stiff for Hpricot.
116
+ Named after why the luck stiff's Hpricot, which made this possible.
116
117
 
117
118
 
118
119
  Copyright (c) 2009 Lou Zell, released under the MIT license
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
+ require 'benchmark'
3
+
4
+ last_fm_example = %(<?xml version="1.0" encoding="utf-8"?>
5
+ <events>
6
+ <event>
7
+ <id>895664</id>
8
+ <title>Lydia</title>
9
+ <artists>
10
+ <artist>Lydia</artist>
11
+ <artist>Black Gold</artist>
12
+
13
+ <headliner>Lydia</headliner>
14
+ </artists>
15
+ <venue>
16
+ <name>Mercury Lounge</name>
17
+ <location>
18
+ <city>New York</city>
19
+ <country>United States</country>
20
+
21
+ <street>217 East Houston Street</street>
22
+ <postalcode>10002</postalcode>
23
+ <timezone>EST</timezone>
24
+
25
+ </location>
26
+ <url>http://www.last.fm/venue/8899833</url>
27
+ </venue>
28
+ <startDate>Thu, 05 Mar 2009</startDate>
29
+ <startTime>18:30</startTime>
30
+ <description><![CDATA[<div class="bbcode">On Sale Fri 1/16 at Noon<br />
31
+ 21+<br />
32
+ $10<br />
33
+ Doors 6:30pm/ Show 7:30pm</div>]]></description>
34
+ <image size="small">http://userserve-ak.last.fm/serve/34/9158303.jpg</image>
35
+
36
+ <image size="medium">http://userserve-ak.last.fm/serve/64/9158303.jpg</image>
37
+ <image size="large">http://userserve-ak.last.fm/serve/126/9158303.jpg</image>
38
+ <attendance>7</attendance>
39
+ <reviews>0</reviews>
40
+ <tag>lastfm:event=895664</tag>
41
+ <url>http://www.last.fm/event/895664</url>
42
+
43
+ </event>
44
+ <event>
45
+ <id>924763</id>
46
+ <title>Stars Like Fleas</title>
47
+ <artists>
48
+ <artist>Stars Like Fleas</artist>
49
+
50
+ <artist>Frances</artist>
51
+ <artist>twi the humble feather</artist>
52
+ <artist>La Strada</artist>
53
+ <headliner>Stars Like Fleas</headliner>
54
+ </artists>
55
+ <venue>
56
+ <name>Music Hall of Williamsburg</name>
57
+
58
+ <location>
59
+ <city>Brooklyn, NY</city>
60
+ <country>United States</country>
61
+ <street>66 North 6th Street</street>
62
+ <postalcode>11211</postalcode>
63
+ <timezone>EST</timezone>
64
+ </location>
65
+ <url>http://www.last.fm/venue/8851989</url>
66
+ </venue>
67
+ <startDate>Thu, 05 Mar 2009</startDate>
68
+
69
+ <startTime>19:00</startTime>
70
+ <description><![CDATA[<div class="bbcode">Doors 7 p.m. / Show 8 p.m.<br />
71
+ $10 advance / $12 day of show<br />
72
+ 18+<br />
73
+ <br />
74
+ On sale Wed. 2/4 at noon</div>]]></description>
75
+ <image size="small">http://userserve-ak.last.fm/serve/34/3598785.jpg</image>
76
+ <image size="medium">http://userserve-ak.last.fm/serve/64/3598785.jpg</image>
77
+ <image size="large">http://userserve-ak.last.fm/serve/126/3598785.jpg</image>
78
+ <attendance>1</attendance>
79
+
80
+ <reviews>0</reviews>
81
+ <tag>lastfm:event=924763</tag>
82
+ <url>http://www.last.fm/event/924763</url>
83
+ </event>
84
+ </events>
85
+
86
+ )
87
+
88
+
89
+ class Response < Mapricot::Base
90
+ has_many :events, :xml
91
+ end
92
+
93
+ class Event < Mapricot::Base
94
+ has_one :id, :integer
95
+ has_one :title, :string
96
+ has_one :artist_group, :xml, :tag_name => "artists"
97
+ has_one :venue, :xml
98
+ end
99
+
100
+ class ArtistGroup < Mapricot::Base
101
+ has_many :artists, :string
102
+ has_one :headliner, :string
103
+ end
104
+
105
+ class Venue < Mapricot::Base
106
+ has_one :name, :string
107
+ end
108
+
109
+ lfm = Response.new(:xml => last_fm_example)
110
+
111
+
112
+ n = 200
113
+ Benchmark.bm do |x|
114
+ x.report {
115
+ Mapricot.parser = :hpricot;
116
+ n.times { lfm = Response.new(:xml => last_fm_example) }
117
+ }
118
+ x.report {
119
+ Mapricot.parser = :libxml;
120
+ n.times { lfm = Response.new(:xml => last_fm_example) }
121
+ }
122
+ x.report {
123
+ Mapricot.parser = :nokogiri;
124
+ n.times { lfm = Response.new(:xml => last_fm_example) }
125
+ }
126
+
127
+ end
@@ -1,10 +1,13 @@
1
- require '../lib/mapricot'
2
- require 'spec'
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
3
2
 
4
- # Using a Facebook example:
5
- XML = %(
6
- <?xml version="1.0" encoding="UTF-8"?>
7
- <users_getInfo_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
3
+ # Using a Facebook example
4
+ # This xml is taken straight from here: http://wiki.developers.facebook.com/index.php/Users.getInfo
5
+ # Note, libxml does not like this for some reason:
6
+ # <users_getInfo_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
7
+ # So 'xmlns="http://api.facebook.com/1.0/"' has been stripped from tag
8
+ # Because of this, for real requests we will have to use hpricot or nokogiri
9
+ FACEBOOK_XML = %(<?xml version="1.0" encoding="UTF-8"?>
10
+ <users_getInfo_response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
8
11
  <user>
9
12
  <uid>8055</uid>
10
13
  <about_me>This field perpetuates the glorification of the ego. Also, it has a character limit.</about_me>
@@ -27,7 +30,7 @@ XML = %(
27
30
  <zip>94303</zip>
28
31
  </current_location>
29
32
  </user>
30
- </users_getInfo_reponse>
33
+ </users_getInfo_response>
31
34
  )
32
35
 
33
36
 
@@ -64,55 +67,19 @@ class CurrentLocation < Mapricot::Base
64
67
  end
65
68
 
66
69
 
67
- describe UsersGetInfoResponse do
68
- before(:all) { @response = UsersGetInfoResponse.new(:xml => XML) }
69
-
70
- it "should respond to users" do
71
- @response.should respond_to(:users)
72
- end
73
-
74
- it "should return an array of size 1 when sent users" do
75
- @response.users.class.should equal(Array)
76
- @response.users.size.should equal(1)
77
- end
78
- end
79
-
80
- describe "response.users.first" do
81
- before(:all) do
82
- response = UsersGetInfoResponse.new(:xml => XML)
83
- @first_user = response.users.first
84
- end
85
-
86
- it "should be of class User" do
87
- @first_user.class.should equal(User)
88
- end
89
-
90
- it "should respond to activities" do
91
- @first_user.should respond_to(:activities)
92
- @first_user.activities.should == "Here: facebook, etc. There: Glee Club, a capella, teaching."
93
- end
94
-
95
- it "should respond to current_location" do
96
- @first_user.should respond_to(:current_location)
97
- end
98
- end
70
+ response = UsersGetInfoResponse.new(:xml => FACEBOOK_XML)
71
+ puts response.users.class # => Array
72
+ puts response.users.size # => 1
99
73
 
74
+ user = response.users.first
100
75
 
101
- describe "response.users.first.current_location" do
102
- before(:all) do
103
- response = UsersGetInfoResponse.new(:xml => XML)
104
- @current_location = response.users.first.current_location
105
- end
106
-
107
- it "should have class CurrentLocation" do
108
- @current_location.class.should equal(CurrentLocation)
109
- end
110
-
111
- it "should respond to city, state, country, and zip" do
112
- @current_location.city.should == 'Palo Alto'
113
- @current_location.state.should == 'CA'
114
- @current_location.country.should == 'United States'
115
- @current_location.zip.should == 94303
116
- end
117
- end
76
+ puts user.uid # => 8055
77
+ puts user.activities # => "Here: facebook, etc. There: Glee Club, a capella, teaching."
78
+ puts user.current_location.city # => "Palo Alto"
79
+ puts user.current_location.state # => "CA"
80
+ puts user.current_location.country # => "United States"
81
+ puts user.current_location.zip # => 94303
118
82
 
83
+ # need to remove redundancy here:
84
+ puts user.affiliation_list.affiliations.first.name # => "Facebook Developers"
85
+ puts user.affiliation_list.affiliations.first.nid # => 50453093
@@ -8,7 +8,7 @@
8
8
  # Response.new(:xml => "some string of xml")
9
9
 
10
10
  # If you do not have an API key, see examples/lastfm_api_no_request.rb
11
- require '../lib/mapricot'
11
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
12
12
 
13
13
  class Response < Mapricot::Base
14
14
  has_many :events, :xml
@@ -1,4 +1,4 @@
1
- require '../lib/mapricot'
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
2
 
3
3
 
4
4
  last_fm_example = %(
@@ -1,4 +1,4 @@
1
- require '../lib/mapricot'
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
2
 
3
3
  # super simple
4
4
  simple_xml = %(
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
+
3
+
4
+ xml = %(
5
+ <response>
6
+ <user id="32" name="Bob"></user>
7
+ <user id="33" name="Sally"></user>
8
+ </response>
9
+ )
10
+
11
+
12
+ class Response < Mapricot::Base
13
+ has_many :users, :xml
14
+ end
15
+
16
+ class User < Mapricot::Base
17
+ has_attribute :id
18
+ has_attribute :name
19
+ end
20
+
21
+ response = Response.new(:xml => xml)
22
+
23
+ response.users.each do |user|
24
+ puts user.name
25
+ puts user.id
26
+ end
@@ -0,0 +1,121 @@
1
+ require 'open-uri'
2
+ require 'rubygems'
3
+ # gem 'hpricot', '=0.6.164'
4
+ require 'hpricot'
5
+ require 'libxml'
6
+ require 'nokogiri'
7
+
8
+
9
+ module Mapricot
10
+ @parser = :hpricot
11
+ class << self; attr_accessor :parser; end
12
+
13
+ # AbstractDoc should be able to find tags, get inner tag content. Find all tags (return an array)
14
+ # I think I will also need AbstractNode
15
+
16
+ class AbstractDoc
17
+
18
+ def self.from_url(url)
19
+ adoc = new
20
+ adoc.url = url
21
+ adoc
22
+ end
23
+
24
+ def self.from_string(string)
25
+ adoc = new
26
+ adoc.string = string
27
+ adoc
28
+ end
29
+
30
+ def url=(url)
31
+ if Mapricot.parser == :libxml
32
+ @udoc = LibXML::XML::Parser.file(url).parse
33
+ elsif Mapricot.parser == :hpricot
34
+ @udoc = Hpricot::XML(open(url))
35
+ elsif Mapricot.paser == :nokogiri
36
+ @udoc = Nokogiri::HTML(open(url))
37
+ end
38
+ end
39
+
40
+ def string=(string)
41
+ if Mapricot.parser == :libxml
42
+ @udoc = LibXML::XML::Parser.string(string).parse
43
+ elsif Mapricot.parser == :hpricot
44
+ @udoc = Hpricot::XML(string)
45
+ elsif Mapricot.parser == :nokogiri
46
+ @udoc = Nokogiri::XML(string)
47
+ end
48
+ end
49
+
50
+
51
+ def find(tagname)
52
+ if Mapricot.parser == :libxml
53
+ AbstractNodeList.new(@udoc.find("//#{tagname}")) # hmm...
54
+ elsif Mapricot.parser == :hpricot
55
+ # AbstractNodeList.new(@udoc/tagname)
56
+ AbstractNodeList.new(@udoc/"//#{tagname}")
57
+ elsif Mapricot.parser == :nokogiri
58
+ AbstractNodeList.new(@udoc.search(tagname))
59
+ # AbstractNodeList.new(@udoc.xpath("//#{tagname}"))
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+
66
+
67
+ class AbstractNodeList
68
+ include Enumerable
69
+
70
+ def initialize(node_list)
71
+ @unode_list = node_list
72
+ end
73
+
74
+ def each(&block)
75
+ @unode_list.each {|unode| yield(AbstractNode.new(unode))}
76
+ end
77
+
78
+ def [](i)
79
+ @unode_list[i]
80
+ end
81
+
82
+ def first
83
+ AbstractNode.new(@unode_list.first)
84
+ end
85
+
86
+ def empty?
87
+ @unode_list.empty?
88
+ end
89
+ end
90
+
91
+
92
+ class AbstractNode
93
+ attr_reader :unode
94
+
95
+ def initialize(unode)
96
+ @unode = unode # unresolved node
97
+ end
98
+
99
+ def to_s
100
+ @unode.to_s
101
+ end
102
+
103
+ def attributes
104
+ if Mapricot.parser != :nokogiri
105
+ @unode.attributes
106
+ else
107
+ atts = {}
108
+ @unode.attributes.each {|k,v| atts[k] = v.value}
109
+ atts
110
+ end
111
+ end
112
+
113
+ def contents
114
+ if Mapricot.parser == :libxml || Mapricot.parser == :nokogiri
115
+ @unode.content
116
+ else
117
+ @unode.inner_html
118
+ end
119
+ end
120
+ end
121
+ end