kind_dom 0.9.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/README +30 -0
- data/lib/kind_dom.rb +119 -0
- data/test/flickr_rss.xml +526 -0
- data/test/kind_dom_test.rb +90 -0
- metadata +82 -0
data/README
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
KindDom provides fail-safe access to the the DOM of an XML document using
|
2
|
+
three methods:
|
3
|
+
- #collection_of to select a collection of nodes
|
4
|
+
- #first_of to select one node
|
5
|
+
- #content_for to get node content.
|
6
|
+
|
7
|
+
The original libxml behavior of the parsed document is preserved.
|
8
|
+
|
9
|
+
As a contrived example, in the controller:
|
10
|
+
@results = KindDom.new(xml_data)
|
11
|
+
|
12
|
+
In the view:
|
13
|
+
<% @results.first_of('//item') do |item| -%>
|
14
|
+
<% item.content_for('description') do |description| -%>
|
15
|
+
<!-- this block is only executed if `item` & `description` is found -->
|
16
|
+
<p><%=h description %></p>
|
17
|
+
<% end -%>
|
18
|
+
<% end -%>
|
19
|
+
|
20
|
+
Project Home http://code.google.com/p/ruby-kind-dom/
|
21
|
+
|
22
|
+
(The MIT License)
|
23
|
+
|
24
|
+
Copyright (c) 2008 Scout Labs Inc. http://scoutlabs.com
|
25
|
+
|
26
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
27
|
+
|
28
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
29
|
+
|
30
|
+
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/kind_dom.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'object_proxy'
|
2
|
+
require 'active_support'
|
3
|
+
require 'xml/libxml'
|
4
|
+
|
5
|
+
|
6
|
+
# KindDom provides fail-safe access to the the DOM of an XML document using
|
7
|
+
# three methods:
|
8
|
+
# - #collection_of to select a collection of nodes
|
9
|
+
# - #first_of to select one node
|
10
|
+
# - #content_for to get node content.
|
11
|
+
#
|
12
|
+
# The original libxml behavior of the parsed document is preserved.
|
13
|
+
#
|
14
|
+
# As a contrived example, in the controller:
|
15
|
+
# @results = KindDom.new(xml_data)
|
16
|
+
#
|
17
|
+
# In the view:
|
18
|
+
# <% @results.first_of('//item') do |item| -%>
|
19
|
+
# <% item.content_for('description') do |description| -%>
|
20
|
+
# <!-- this block is only executed if `item` & `description` is found -->
|
21
|
+
# <p><%=h description %></p>
|
22
|
+
# <% end -%>
|
23
|
+
# <% end -%>
|
24
|
+
#
|
25
|
+
class KindDom < ObjectProxy
|
26
|
+
|
27
|
+
attr_accessor :dom
|
28
|
+
|
29
|
+
def initialize(raw_xml=nil)
|
30
|
+
unless raw_xml.nil?
|
31
|
+
parser = XML::Parser.new
|
32
|
+
parser.string = raw_xml
|
33
|
+
@dom = parser.parse
|
34
|
+
end
|
35
|
+
rescue XML::Parser::ParseError
|
36
|
+
ensure
|
37
|
+
@dom.extend Kindness
|
38
|
+
super(@dom) # Proxy all method calls to @dom.
|
39
|
+
end
|
40
|
+
|
41
|
+
module Kindness
|
42
|
+
# Retrieve the contents of the first node or attribute selected by the XPath.
|
43
|
+
#
|
44
|
+
# Optional second argument is the default value to return if the DOM find fails.
|
45
|
+
#
|
46
|
+
# When a block is provided, it will be used to transform the found content
|
47
|
+
# (or default) before returning.
|
48
|
+
#
|
49
|
+
# The block should except one argument: the content to tranform.
|
50
|
+
#
|
51
|
+
def content_for(xpath, default=nil)
|
52
|
+
node = case self.class.to_s
|
53
|
+
when 'XML::Document' then
|
54
|
+
root.find_first(xpath)
|
55
|
+
else # 'XML::Node'
|
56
|
+
find_first(xpath)
|
57
|
+
end
|
58
|
+
content = case node.class.to_s
|
59
|
+
when 'XML::Attr' then
|
60
|
+
node.value
|
61
|
+
else
|
62
|
+
node.content
|
63
|
+
end
|
64
|
+
rescue NoMethodError
|
65
|
+
ensure
|
66
|
+
content = content.blank? ? default : content
|
67
|
+
if block_given? and !content.blank?
|
68
|
+
return yield(content)
|
69
|
+
else
|
70
|
+
return content
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Retrieve a collection (Array) of DOM nodes selected by the XPath.
|
75
|
+
#
|
76
|
+
# Each node is extended with Kindness to support #content_for, #collection_of & #first_of.
|
77
|
+
#
|
78
|
+
# When a block is provided, it will be used to transform the found collection
|
79
|
+
# (or default) before returning.
|
80
|
+
#
|
81
|
+
def collection_of(xpath, default=nil)
|
82
|
+
c = find(xpath).collect {|n| n.extend Kindness }
|
83
|
+
rescue NoMethodError
|
84
|
+
ensure
|
85
|
+
c = c.blank?||c.size<1 ? default : c
|
86
|
+
if block_given? and !c.nil?
|
87
|
+
return yield(c)
|
88
|
+
else
|
89
|
+
return c
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Retrieve the first DOM node selected by the XPath.
|
94
|
+
#
|
95
|
+
# The node is extended with Kindness to support #content_for, #collection_of & #first_of.
|
96
|
+
#
|
97
|
+
# When a block is provided, it will be used to transform the found node
|
98
|
+
# (or default) before returning.
|
99
|
+
#
|
100
|
+
def first_of(xpath, default=nil)
|
101
|
+
n = case self.class.to_s
|
102
|
+
when 'XML::Document' then
|
103
|
+
root.find_first(xpath)
|
104
|
+
else # 'XML::Node'
|
105
|
+
find_first(xpath)
|
106
|
+
end
|
107
|
+
n.extend Kindness
|
108
|
+
rescue NoMethodError
|
109
|
+
ensure
|
110
|
+
n = n.blank? ? default : n
|
111
|
+
if block_given? and !n.blank?
|
112
|
+
return yield(n)
|
113
|
+
else
|
114
|
+
return n
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
data/test/flickr_rss.xml
ADDED
@@ -0,0 +1,526 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<rss version="2.0"
|
3
|
+
xmlns:media="http://search.yahoo.com/mrss/"
|
4
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
5
|
+
xmlns:flickr="http://flickr.com/services/feeds/"
|
6
|
+
>
|
7
|
+
<channel>
|
8
|
+
<title>Photos from marsi</title>
|
9
|
+
<link>http://www.flickr.com/photos/marsi/</link>
|
10
|
+
<description></description>
|
11
|
+
<pubDate>Sun, 23 Mar 2008 15:35:21 -0800</pubDate>
|
12
|
+
<lastBuildDate>Sun, 23 Mar 2008 15:35:21 -0800</lastBuildDate>
|
13
|
+
<generator>http://www.flickr.com/</generator>
|
14
|
+
<image>
|
15
|
+
<url>http://farm1.static.flickr.com/43/buddyicons/66615882@N00.jpg?1205892764#66615882@N00</url>
|
16
|
+
<title>Photos from marsi</title>
|
17
|
+
<link>http://www.flickr.com/photos/marsi/</link>
|
18
|
+
</image>
|
19
|
+
|
20
|
+
<item>
|
21
|
+
<title>Alaya Cove</title>
|
22
|
+
<link>http://www.flickr.com/photos/marsi/2355265931/</link>
|
23
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
24
|
+
<p><a href="http://www.flickr.com/photos/marsi/2355265931/" title="Alaya Cove"><img src="http://farm3.static.flickr.com/2152/2355265931_c1750f4f82_m.jpg" width="240" height="180" alt="Alaya Cove" /></a></p>
|
25
|
+
|
26
|
+
<p>at Angel Island, the ferry landing</p></description>
|
27
|
+
<pubDate>Sun, 23 Mar 2008 15:35:21 -0800</pubDate>
|
28
|
+
<dc:date.Taken>2008-03-23T10:37:13-08:00</dc:date.Taken>
|
29
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
30
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2355265931</guid>
|
31
|
+
<media:content url="http://farm3.static.flickr.com/2152/2355265931_8777ff38c1_o.jpg"
|
32
|
+
type="image/jpeg"
|
33
|
+
height="1500"
|
34
|
+
width="2000"/>
|
35
|
+
<media:title>Alaya Cove</media:title>
|
36
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
37
|
+
<p><a href="http://www.flickr.com/photos/marsi/2355265931/" title="Alaya Cove"><img src="http://farm3.static.flickr.com/2152/2355265931_c1750f4f82_m.jpg" width="240" height="180" alt="Alaya Cove" /></a></p>
|
38
|
+
|
39
|
+
<p>at Angel Island, the ferry landing</p></media:text>
|
40
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2152/2355265931_c1750f4f82_s.jpg" height="75" width="75" />
|
41
|
+
<media:credit role="photographer">marsi</media:credit>
|
42
|
+
<media:category scheme="urn:flickr:tags">boats cove angelisland</media:category>
|
43
|
+
|
44
|
+
</item>
|
45
|
+
<item>
|
46
|
+
<title>stained glass paper bag</title>
|
47
|
+
<link>http://www.flickr.com/photos/marsi/2356098262/</link>
|
48
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
49
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356098262/" title="stained glass paper bag"><img src="http://farm4.static.flickr.com/3012/2356098262_40ffffbabc_m.jpg" width="240" height="180" alt="stained glass paper bag" /></a></p>
|
50
|
+
|
51
|
+
<p>a paper bag previously full of buttery shortbread</p></description>
|
52
|
+
<pubDate>Sun, 23 Mar 2008 15:35:04 -0800</pubDate>
|
53
|
+
<dc:date.Taken>2008-03-22T16:23:10-08:00</dc:date.Taken>
|
54
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
55
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2356098262</guid>
|
56
|
+
<media:content url="http://farm4.static.flickr.com/3012/2356098262_4f647a68b8_o.jpg"
|
57
|
+
type="image/jpeg"
|
58
|
+
height="1500"
|
59
|
+
width="2000"/>
|
60
|
+
<media:title>stained glass paper bag</media:title>
|
61
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
62
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356098262/" title="stained glass paper bag"><img src="http://farm4.static.flickr.com/3012/2356098262_40ffffbabc_m.jpg" width="240" height="180" alt="stained glass paper bag" /></a></p>
|
63
|
+
|
64
|
+
<p>a paper bag previously full of buttery shortbread</p></media:text>
|
65
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3012/2356098262_40ffffbabc_s.jpg" height="75" width="75" />
|
66
|
+
<media:credit role="photographer">marsi</media:credit>
|
67
|
+
|
68
|
+
</item>
|
69
|
+
<item>
|
70
|
+
<title>"dive in"</title>
|
71
|
+
<link>http://www.flickr.com/photos/marsi/2356097566/</link>
|
72
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
73
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356097566/" title="&quot;dive in&quot;"><img src="http://farm3.static.flickr.com/2316/2356097566_c2c293bbca_m.jpg" width="240" height="180" alt="&quot;dive in&quot;" /></a></p>
|
74
|
+
|
75
|
+
<p>if only I were a bumble bee</p></description>
|
76
|
+
<pubDate>Sun, 23 Mar 2008 15:34:49 -0800</pubDate>
|
77
|
+
<dc:date.Taken>2008-03-22T14:08:05-08:00</dc:date.Taken>
|
78
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
79
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2356097566</guid>
|
80
|
+
<media:content url="http://farm3.static.flickr.com/2316/2356097566_c44a306704_o.jpg"
|
81
|
+
type="image/jpeg"
|
82
|
+
height="1500"
|
83
|
+
width="2000"/>
|
84
|
+
<media:title>"dive in"</media:title>
|
85
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
86
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356097566/" title="&quot;dive in&quot;"><img src="http://farm3.static.flickr.com/2316/2356097566_c2c293bbca_m.jpg" width="240" height="180" alt="&quot;dive in&quot;" /></a></p>
|
87
|
+
|
88
|
+
<p>if only I were a bumble bee</p></media:text>
|
89
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2316/2356097566_c2c293bbca_s.jpg" height="75" width="75" />
|
90
|
+
<media:credit role="photographer">marsi</media:credit>
|
91
|
+
<media:category scheme="urn:flickr:tags">orange flower poppy bloom angelisland</media:category>
|
92
|
+
|
93
|
+
</item>
|
94
|
+
<item>
|
95
|
+
<title>Graham & Josh</title>
|
96
|
+
<link>http://www.flickr.com/photos/marsi/2355263497/</link>
|
97
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
98
|
+
<p><a href="http://www.flickr.com/photos/marsi/2355263497/" title="Graham &amp; Josh"><img src="http://farm4.static.flickr.com/3289/2355263497_5b19703602_m.jpg" width="240" height="180" alt="Graham &amp; Josh" /></a></p>
|
99
|
+
|
100
|
+
</description>
|
101
|
+
<pubDate>Sun, 23 Mar 2008 15:34:33 -0800</pubDate>
|
102
|
+
<dc:date.Taken>2008-03-22T13:45:17-08:00</dc:date.Taken>
|
103
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
104
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2355263497</guid>
|
105
|
+
<media:content url="http://farm4.static.flickr.com/3289/2355263497_abfefc758c_o.jpg"
|
106
|
+
type="image/jpeg"
|
107
|
+
height="1500"
|
108
|
+
width="2000"/>
|
109
|
+
<media:title>Graham & Josh</media:title>
|
110
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
111
|
+
<p><a href="http://www.flickr.com/photos/marsi/2355263497/" title="Graham &amp; Josh"><img src="http://farm4.static.flickr.com/3289/2355263497_5b19703602_m.jpg" width="240" height="180" alt="Graham &amp; Josh" /></a></p>
|
112
|
+
|
113
|
+
</media:text>
|
114
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3289/2355263497_5b19703602_s.jpg" height="75" width="75" />
|
115
|
+
<media:credit role="photographer">marsi</media:credit>
|
116
|
+
<media:category scheme="urn:flickr:tags">snapshot angelisland</media:category>
|
117
|
+
|
118
|
+
</item>
|
119
|
+
<item>
|
120
|
+
<title>Northeast view from Angel Island</title>
|
121
|
+
<link>http://www.flickr.com/photos/marsi/2356095812/</link>
|
122
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
123
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356095812/" title="Northeast view from Angel Island"><img src="http://farm3.static.flickr.com/2005/2356095812_059dc9dc75_m.jpg" width="240" height="180" alt="Northeast view from Angel Island" /></a></p>
|
124
|
+
|
125
|
+
</description>
|
126
|
+
<pubDate>Sun, 23 Mar 2008 15:34:13 -0800</pubDate>
|
127
|
+
<dc:date.Taken>2008-03-22T13:44:40-08:00</dc:date.Taken>
|
128
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
129
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2356095812</guid>
|
130
|
+
<media:content url="http://farm3.static.flickr.com/2005/2356095812_9dc360fb02_o.jpg"
|
131
|
+
type="image/jpeg"
|
132
|
+
height="1500"
|
133
|
+
width="2000"/>
|
134
|
+
<media:title>Northeast view from Angel Island</media:title>
|
135
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
136
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356095812/" title="Northeast view from Angel Island"><img src="http://farm3.static.flickr.com/2005/2356095812_059dc9dc75_m.jpg" width="240" height="180" alt="Northeast view from Angel Island" /></a></p>
|
137
|
+
|
138
|
+
</media:text>
|
139
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2005/2356095812_059dc9dc75_s.jpg" height="75" width="75" />
|
140
|
+
<media:credit role="photographer">marsi</media:credit>
|
141
|
+
<media:category scheme="urn:flickr:tags">angelisland tiburon kayakcamp</media:category>
|
142
|
+
|
143
|
+
</item>
|
144
|
+
<item>
|
145
|
+
<title>campers settling in</title>
|
146
|
+
<link>http://www.flickr.com/photos/marsi/2356094942/</link>
|
147
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
148
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356094942/" title="campers settling in"><img src="http://farm3.static.flickr.com/2389/2356094942_54ba7d6fda_m.jpg" width="240" height="180" alt="campers settling in" /></a></p>
|
149
|
+
|
150
|
+
</description>
|
151
|
+
<pubDate>Sun, 23 Mar 2008 15:33:53 -0800</pubDate>
|
152
|
+
<dc:date.Taken>2008-03-22T12:53:58-08:00</dc:date.Taken>
|
153
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
154
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2356094942</guid>
|
155
|
+
<media:content url="http://farm3.static.flickr.com/2389/2356094942_4d6987c1fa_o.jpg"
|
156
|
+
type="image/jpeg"
|
157
|
+
height="1500"
|
158
|
+
width="2000"/>
|
159
|
+
<media:title>campers settling in</media:title>
|
160
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
161
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356094942/" title="campers settling in"><img src="http://farm3.static.flickr.com/2389/2356094942_54ba7d6fda_m.jpg" width="240" height="180" alt="campers settling in" /></a></p>
|
162
|
+
|
163
|
+
</media:text>
|
164
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2389/2356094942_54ba7d6fda_s.jpg" height="75" width="75" />
|
165
|
+
<media:credit role="photographer">marsi</media:credit>
|
166
|
+
<media:category scheme="urn:flickr:tags">angelisland kayakcamp</media:category>
|
167
|
+
|
168
|
+
</item>
|
169
|
+
<item>
|
170
|
+
<title>vivid Angel Island flora</title>
|
171
|
+
<link>http://www.flickr.com/photos/marsi/2356094180/</link>
|
172
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
173
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356094180/" title="vivid Angel Island flora"><img src="http://farm4.static.flickr.com/3061/2356094180_929589aa41_m.jpg" width="240" height="180" alt="vivid Angel Island flora" /></a></p>
|
174
|
+
|
175
|
+
</description>
|
176
|
+
<pubDate>Sun, 23 Mar 2008 15:33:36 -0800</pubDate>
|
177
|
+
<dc:date.Taken>2008-03-22T12:52:53-08:00</dc:date.Taken>
|
178
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
179
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2356094180</guid>
|
180
|
+
<media:content url="http://farm4.static.flickr.com/3061/2356094180_ee2c3a6f5b_o.jpg"
|
181
|
+
type="image/jpeg"
|
182
|
+
height="1500"
|
183
|
+
width="2000"/>
|
184
|
+
<media:title>vivid Angel Island flora</media:title>
|
185
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
186
|
+
<p><a href="http://www.flickr.com/photos/marsi/2356094180/" title="vivid Angel Island flora"><img src="http://farm4.static.flickr.com/3061/2356094180_929589aa41_m.jpg" width="240" height="180" alt="vivid Angel Island flora" /></a></p>
|
187
|
+
|
188
|
+
</media:text>
|
189
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3061/2356094180_929589aa41_s.jpg" height="75" width="75" />
|
190
|
+
<media:credit role="photographer">marsi</media:credit>
|
191
|
+
<media:category scheme="urn:flickr:tags">flowers flora purple blooms angelisland</media:category>
|
192
|
+
|
193
|
+
</item>
|
194
|
+
<item>
|
195
|
+
<title>covert seal observation unit</title>
|
196
|
+
<link>http://www.flickr.com/photos/marsi/2355259849/</link>
|
197
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
198
|
+
<p><a href="http://www.flickr.com/photos/marsi/2355259849/" title="covert seal observation unit"><img src="http://farm4.static.flickr.com/3180/2355259849_410df80ffe_m.jpg" width="240" height="180" alt="covert seal observation unit" /></a></p>
|
199
|
+
|
200
|
+
</description>
|
201
|
+
<pubDate>Sun, 23 Mar 2008 15:33:15 -0800</pubDate>
|
202
|
+
<dc:date.Taken>2008-03-22T12:46:27-08:00</dc:date.Taken>
|
203
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
204
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2355259849</guid>
|
205
|
+
<media:content url="http://farm4.static.flickr.com/3180/2355259849_5506dbf63c_o.jpg"
|
206
|
+
type="image/jpeg"
|
207
|
+
height="1500"
|
208
|
+
width="2000"/>
|
209
|
+
<media:title>covert seal observation unit</media:title>
|
210
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
211
|
+
<p><a href="http://www.flickr.com/photos/marsi/2355259849/" title="covert seal observation unit"><img src="http://farm4.static.flickr.com/3180/2355259849_410df80ffe_m.jpg" width="240" height="180" alt="covert seal observation unit" /></a></p>
|
212
|
+
|
213
|
+
</media:text>
|
214
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3180/2355259849_410df80ffe_s.jpg" height="75" width="75" />
|
215
|
+
<media:credit role="photographer">marsi</media:credit>
|
216
|
+
<media:category scheme="urn:flickr:tags">angelisland selfshot</media:category>
|
217
|
+
|
218
|
+
</item>
|
219
|
+
<item>
|
220
|
+
<title>WTFBBQMATE</title>
|
221
|
+
<link>http://www.flickr.com/photos/marsi/2343888675/</link>
|
222
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
223
|
+
<p><a href="http://www.flickr.com/photos/marsi/2343888675/" title="WTFBBQMATE"><img src="http://farm4.static.flickr.com/3087/2343888675_d8e20acb41_m.jpg" width="240" height="180" alt="WTFBBQMATE" /></a></p>
|
224
|
+
|
225
|
+
</description>
|
226
|
+
<pubDate>Tue, 18 Mar 2008 19:06:29 -0800</pubDate>
|
227
|
+
<dc:date.Taken>2008-03-17T19:21:26-08:00</dc:date.Taken>
|
228
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
229
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2343888675</guid>
|
230
|
+
<media:content url="http://farm4.static.flickr.com/3087/2343888675_0ea6616a76_o.jpg"
|
231
|
+
type="image/jpeg"
|
232
|
+
height="1500"
|
233
|
+
width="2000"/>
|
234
|
+
<media:title>WTFBBQMATE</media:title>
|
235
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
236
|
+
<p><a href="http://www.flickr.com/photos/marsi/2343888675/" title="WTFBBQMATE"><img src="http://farm4.static.flickr.com/3087/2343888675_d8e20acb41_m.jpg" width="240" height="180" alt="WTFBBQMATE" /></a></p>
|
237
|
+
|
238
|
+
</media:text>
|
239
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3087/2343888675_d8e20acb41_s.jpg" height="75" width="75" />
|
240
|
+
<media:credit role="photographer">marsi</media:credit>
|
241
|
+
|
242
|
+
</item>
|
243
|
+
<item>
|
244
|
+
<title>St. Patricks Day</title>
|
245
|
+
<link>http://www.flickr.com/photos/marsi/2344716850/</link>
|
246
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
247
|
+
<p><a href="http://www.flickr.com/photos/marsi/2344716850/" title="St. Patricks Day"><img src="http://farm3.static.flickr.com/2334/2344716850_fc105cfbbe_m.jpg" width="240" height="180" alt="St. Patricks Day" /></a></p>
|
248
|
+
|
249
|
+
<p>with Bob &amp; Tony</p></description>
|
250
|
+
<pubDate>Tue, 18 Mar 2008 19:05:22 -0800</pubDate>
|
251
|
+
<dc:date.Taken>2008-03-17T19:21:11-08:00</dc:date.Taken>
|
252
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
253
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2344716850</guid>
|
254
|
+
<media:content url="http://farm3.static.flickr.com/2334/2344716850_0febde2dd5_o.jpg"
|
255
|
+
type="image/jpeg"
|
256
|
+
height="1500"
|
257
|
+
width="2000"/>
|
258
|
+
<media:title>St. Patricks Day</media:title>
|
259
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
260
|
+
<p><a href="http://www.flickr.com/photos/marsi/2344716850/" title="St. Patricks Day"><img src="http://farm3.static.flickr.com/2334/2344716850_fc105cfbbe_m.jpg" width="240" height="180" alt="St. Patricks Day" /></a></p>
|
261
|
+
|
262
|
+
<p>with Bob &amp; Tony</p></media:text>
|
263
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2334/2344716850_fc105cfbbe_s.jpg" height="75" width="75" />
|
264
|
+
<media:credit role="photographer">marsi</media:credit>
|
265
|
+
<media:category scheme="urn:flickr:tags">selfshot</media:category>
|
266
|
+
|
267
|
+
</item>
|
268
|
+
<item>
|
269
|
+
<title>my salt & pepper</title>
|
270
|
+
<link>http://www.flickr.com/photos/marsi/2338452559/</link>
|
271
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
272
|
+
<p><a href="http://www.flickr.com/photos/marsi/2338452559/" title="my salt &amp; pepper"><img src="http://farm3.static.flickr.com/2034/2338452559_a4ba730701_m.jpg" width="240" height="180" alt="my salt &amp; pepper" /></a></p>
|
273
|
+
|
274
|
+
</description>
|
275
|
+
<pubDate>Sun, 16 Mar 2008 17:21:45 -0800</pubDate>
|
276
|
+
<dc:date.Taken>2008-03-16T15:01:30-08:00</dc:date.Taken>
|
277
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
278
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2338452559</guid>
|
279
|
+
<media:content url="http://farm3.static.flickr.com/2034/2338452559_3bf9078ca7_o.jpg"
|
280
|
+
type="image/jpeg"
|
281
|
+
height="1500"
|
282
|
+
width="2000"/>
|
283
|
+
<media:title>my salt & pepper</media:title>
|
284
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
285
|
+
<p><a href="http://www.flickr.com/photos/marsi/2338452559/" title="my salt &amp; pepper"><img src="http://farm3.static.flickr.com/2034/2338452559_a4ba730701_m.jpg" width="240" height="180" alt="my salt &amp; pepper" /></a></p>
|
286
|
+
|
287
|
+
</media:text>
|
288
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2034/2338452559_a4ba730701_s.jpg" height="75" width="75" />
|
289
|
+
<media:credit role="photographer">marsi</media:credit>
|
290
|
+
<media:category scheme="urn:flickr:tags">hair cut remnents</media:category>
|
291
|
+
|
292
|
+
</item>
|
293
|
+
<item>
|
294
|
+
<title>self-service haircut</title>
|
295
|
+
<link>http://www.flickr.com/photos/marsi/2339284670/</link>
|
296
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
297
|
+
<p><a href="http://www.flickr.com/photos/marsi/2339284670/" title="self-service haircut"><img src="http://farm3.static.flickr.com/2328/2339284670_a27417ac58_m.jpg" width="240" height="192" alt="self-service haircut" /></a></p>
|
298
|
+
|
299
|
+
</description>
|
300
|
+
<pubDate>Sun, 16 Mar 2008 17:21:28 -0800</pubDate>
|
301
|
+
<dc:date.Taken>2008-03-16T15:04:30-08:00</dc:date.Taken>
|
302
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
303
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2339284670</guid>
|
304
|
+
<media:content url="http://farm3.static.flickr.com/2328/2339284670_a040da43e2_o.jpg"
|
305
|
+
type="image/jpeg"
|
306
|
+
height="1147"
|
307
|
+
width="1434"/>
|
308
|
+
<media:title>self-service haircut</media:title>
|
309
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
310
|
+
<p><a href="http://www.flickr.com/photos/marsi/2339284670/" title="self-service haircut"><img src="http://farm3.static.flickr.com/2328/2339284670_a27417ac58_m.jpg" width="240" height="192" alt="self-service haircut" /></a></p>
|
311
|
+
|
312
|
+
</media:text>
|
313
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2328/2339284670_a27417ac58_s.jpg" height="75" width="75" />
|
314
|
+
<media:credit role="photographer">marsi</media:credit>
|
315
|
+
<media:category scheme="urn:flickr:tags">portrait profile</media:category>
|
316
|
+
|
317
|
+
</item>
|
318
|
+
<item>
|
319
|
+
<title>Last Climb</title>
|
320
|
+
<link>http://www.flickr.com/photos/marsi/2323742185/</link>
|
321
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
322
|
+
<p><a href="http://www.flickr.com/photos/marsi/2323742185/" title="Last Climb"><img src="http://farm4.static.flickr.com/3146/2323742185_143bae8d27_m.jpg" width="240" height="180" alt="Last Climb" /></a></p>
|
323
|
+
|
324
|
+
<p>Last climb of the day's exploratory ride. ~240' climb in three blocks, with a spicy 30' rise at 45º (notice the street drop-off at the closest intersection).</p></description>
|
325
|
+
<pubDate>Mon, 10 Mar 2008 08:54:21 -0800</pubDate>
|
326
|
+
<dc:date.Taken>2008-03-09T13:07:46-08:00</dc:date.Taken>
|
327
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
328
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2323742185</guid>
|
329
|
+
<media:content url="http://farm4.static.flickr.com/3146/2323742185_60b967c850_o.jpg"
|
330
|
+
type="image/jpeg"
|
331
|
+
height="1500"
|
332
|
+
width="2000"/>
|
333
|
+
<media:title>Last Climb</media:title>
|
334
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
335
|
+
<p><a href="http://www.flickr.com/photos/marsi/2323742185/" title="Last Climb"><img src="http://farm4.static.flickr.com/3146/2323742185_143bae8d27_m.jpg" width="240" height="180" alt="Last Climb" /></a></p>
|
336
|
+
|
337
|
+
<p>Last climb of the day's exploratory ride. ~240' climb in three blocks, with a spicy 30' rise at 45º (notice the street drop-off at the closest intersection).</p></media:text>
|
338
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3146/2323742185_143bae8d27_s.jpg" height="75" width="75" />
|
339
|
+
<media:credit role="photographer">marsi</media:credit>
|
340
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco landscape bay potrero</media:category>
|
341
|
+
|
342
|
+
</item>
|
343
|
+
<item>
|
344
|
+
<title>Zinger in SF</title>
|
345
|
+
<link>http://www.flickr.com/photos/marsi/2321598135/</link>
|
346
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
347
|
+
<p><a href="http://www.flickr.com/photos/marsi/2321598135/" title="Zinger in SF"><img src="http://farm3.static.flickr.com/2050/2321598135_fb3c8b93fa_m.jpg" width="240" height="100" alt="Zinger in SF" /></a></p>
|
348
|
+
|
349
|
+
<p>Exploratory route through town on the new road cycle.<br />
|
350
|
+
<a href="http://www.gmap-pedometer.com/?r=1686260">www.gmap-pedometer.com/?r=1686260</a><br />
|
351
|
+
<br />
|
352
|
+
21-miles; 700' of climb.</p></description>
|
353
|
+
<pubDate>Sun, 9 Mar 2008 14:59:21 -0800</pubDate>
|
354
|
+
<dc:date.Taken>2008-03-09T14:59:21-08:00</dc:date.Taken>
|
355
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
356
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2321598135</guid>
|
357
|
+
<media:content url="http://farm3.static.flickr.com/2050/2321598135_26e20ee106_o.png"
|
358
|
+
type="image/jpeg"
|
359
|
+
height="417"
|
360
|
+
width="999"/>
|
361
|
+
<media:title>Zinger in SF</media:title>
|
362
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
363
|
+
<p><a href="http://www.flickr.com/photos/marsi/2321598135/" title="Zinger in SF"><img src="http://farm3.static.flickr.com/2050/2321598135_fb3c8b93fa_m.jpg" width="240" height="100" alt="Zinger in SF" /></a></p>
|
364
|
+
|
365
|
+
<p>Exploratory route through town on the new road cycle.<br />
|
366
|
+
<a href="http://www.gmap-pedometer.com/?r=1686260">www.gmap-pedometer.com/?r=1686260</a><br />
|
367
|
+
<br />
|
368
|
+
21-miles; 700' of climb.</p></media:text>
|
369
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2050/2321598135_fb3c8b93fa_s.jpg" height="75" width="75" />
|
370
|
+
<media:credit role="photographer">marsi</media:credit>
|
371
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco bicycle route</media:category>
|
372
|
+
|
373
|
+
</item>
|
374
|
+
<item>
|
375
|
+
<title>Lock it or loose it.</title>
|
376
|
+
<link>http://www.flickr.com/photos/marsi/2303163814/</link>
|
377
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
378
|
+
<p><a href="http://www.flickr.com/photos/marsi/2303163814/" title="Lock it or loose it."><img src="http://farm3.static.flickr.com/2179/2303163814_f586f7c5f0_m.jpg" width="240" height="180" alt="Lock it or loose it." /></a></p>
|
379
|
+
|
380
|
+
<p>@ Divisidero &amp; Fell; fortunately not my bike</p></description>
|
381
|
+
<pubDate>Sat, 1 Mar 2008 13:47:19 -0800</pubDate>
|
382
|
+
<dc:date.Taken>2008-03-01T12:57:35-08:00</dc:date.Taken>
|
383
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
384
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2303163814</guid>
|
385
|
+
<media:content url="http://farm3.static.flickr.com/2179/2303163814_63c0d787b8_o.jpg"
|
386
|
+
type="image/jpeg"
|
387
|
+
height="1500"
|
388
|
+
width="2000"/>
|
389
|
+
<media:title>Lock it or loose it.</media:title>
|
390
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
391
|
+
<p><a href="http://www.flickr.com/photos/marsi/2303163814/" title="Lock it or loose it."><img src="http://farm3.static.flickr.com/2179/2303163814_f586f7c5f0_m.jpg" width="240" height="180" alt="Lock it or loose it." /></a></p>
|
392
|
+
|
393
|
+
<p>@ Divisidero &amp; Fell; fortunately not my bike</p></media:text>
|
394
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2179/2303163814_f586f7c5f0_s.jpg" height="75" width="75" />
|
395
|
+
<media:credit role="photographer">marsi</media:credit>
|
396
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco bicycle crime theft</media:category>
|
397
|
+
|
398
|
+
</item>
|
399
|
+
<item>
|
400
|
+
<title>Passing the Boot</title>
|
401
|
+
<link>http://www.flickr.com/photos/marsi/2301330236/</link>
|
402
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
403
|
+
<p><a href="http://www.flickr.com/photos/marsi/2301330236/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2113/2301330236_16231499f5_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
404
|
+
|
405
|
+
</description>
|
406
|
+
<pubDate>Fri, 29 Feb 2008 17:06:08 -0800</pubDate>
|
407
|
+
<dc:date.Taken>2008-02-28T19:38:55-08:00</dc:date.Taken>
|
408
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
409
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2301330236</guid>
|
410
|
+
<media:content url="http://farm3.static.flickr.com/2113/2301330236_7922dac5ff_o.jpg"
|
411
|
+
type="image/jpeg"
|
412
|
+
height="1500"
|
413
|
+
width="2000"/>
|
414
|
+
<media:title>Passing the Boot</media:title>
|
415
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
416
|
+
<p><a href="http://www.flickr.com/photos/marsi/2301330236/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2113/2301330236_16231499f5_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
417
|
+
|
418
|
+
</media:text>
|
419
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2113/2301330236_16231499f5_s.jpg" height="75" width="75" />
|
420
|
+
<media:credit role="photographer">marsi</media:credit>
|
421
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco beer drinking german suppenkuche</media:category>
|
422
|
+
|
423
|
+
</item>
|
424
|
+
<item>
|
425
|
+
<title>Passing the Boot</title>
|
426
|
+
<link>http://www.flickr.com/photos/marsi/2301330214/</link>
|
427
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
428
|
+
<p><a href="http://www.flickr.com/photos/marsi/2301330214/" title="Passing the Boot"><img src="http://farm4.static.flickr.com/3001/2301330214_6b371825b3_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
429
|
+
|
430
|
+
</description>
|
431
|
+
<pubDate>Fri, 29 Feb 2008 17:06:07 -0800</pubDate>
|
432
|
+
<dc:date.Taken>2008-02-28T19:38:19-08:00</dc:date.Taken>
|
433
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
434
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2301330214</guid>
|
435
|
+
<media:content url="http://farm4.static.flickr.com/3001/2301330214_6b232bc2a5_o.jpg"
|
436
|
+
type="image/jpeg"
|
437
|
+
height="1500"
|
438
|
+
width="2000"/>
|
439
|
+
<media:title>Passing the Boot</media:title>
|
440
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
441
|
+
<p><a href="http://www.flickr.com/photos/marsi/2301330214/" title="Passing the Boot"><img src="http://farm4.static.flickr.com/3001/2301330214_6b371825b3_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
442
|
+
|
443
|
+
</media:text>
|
444
|
+
<media:thumbnail url="http://farm4.static.flickr.com/3001/2301330214_6b371825b3_s.jpg" height="75" width="75" />
|
445
|
+
<media:credit role="photographer">marsi</media:credit>
|
446
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco beer drinking german suppenkuche</media:category>
|
447
|
+
|
448
|
+
</item>
|
449
|
+
<item>
|
450
|
+
<title>Passing the Boot</title>
|
451
|
+
<link>http://www.flickr.com/photos/marsi/2301330182/</link>
|
452
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
453
|
+
<p><a href="http://www.flickr.com/photos/marsi/2301330182/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2396/2301330182_571e7ef1e7_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
454
|
+
|
455
|
+
</description>
|
456
|
+
<pubDate>Fri, 29 Feb 2008 17:06:06 -0800</pubDate>
|
457
|
+
<dc:date.Taken>2008-02-28T19:37:41-08:00</dc:date.Taken>
|
458
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
459
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2301330182</guid>
|
460
|
+
<media:content url="http://farm3.static.flickr.com/2396/2301330182_9a23b99fcc_o.jpg"
|
461
|
+
type="image/jpeg"
|
462
|
+
height="1500"
|
463
|
+
width="2000"/>
|
464
|
+
<media:title>Passing the Boot</media:title>
|
465
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
466
|
+
<p><a href="http://www.flickr.com/photos/marsi/2301330182/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2396/2301330182_571e7ef1e7_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
467
|
+
|
468
|
+
</media:text>
|
469
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2396/2301330182_571e7ef1e7_s.jpg" height="75" width="75" />
|
470
|
+
<media:credit role="photographer">marsi</media:credit>
|
471
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco beer drinking german suppenkuche</media:category>
|
472
|
+
|
473
|
+
</item>
|
474
|
+
<item>
|
475
|
+
<title>Passing the Boot</title>
|
476
|
+
<link>http://www.flickr.com/photos/marsi/2300536709/</link>
|
477
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
478
|
+
<p><a href="http://www.flickr.com/photos/marsi/2300536709/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2335/2300536709_c4fe028bb0_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
479
|
+
|
480
|
+
</description>
|
481
|
+
<pubDate>Fri, 29 Feb 2008 17:06:04 -0800</pubDate>
|
482
|
+
<dc:date.Taken>2008-02-28T19:37:22-08:00</dc:date.Taken>
|
483
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
484
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2300536709</guid>
|
485
|
+
<media:content url="http://farm3.static.flickr.com/2335/2300536709_195ef201a2_o.jpg"
|
486
|
+
type="image/jpeg"
|
487
|
+
height="1500"
|
488
|
+
width="2000"/>
|
489
|
+
<media:title>Passing the Boot</media:title>
|
490
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
491
|
+
<p><a href="http://www.flickr.com/photos/marsi/2300536709/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2335/2300536709_c4fe028bb0_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
492
|
+
|
493
|
+
</media:text>
|
494
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2335/2300536709_c4fe028bb0_s.jpg" height="75" width="75" />
|
495
|
+
<media:credit role="photographer">marsi</media:credit>
|
496
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco beer drinking german suppenkuche</media:category>
|
497
|
+
|
498
|
+
</item>
|
499
|
+
<item>
|
500
|
+
<title>Passing the Boot</title>
|
501
|
+
<link>http://www.flickr.com/photos/marsi/2300536681/</link>
|
502
|
+
<description><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
503
|
+
<p><a href="http://www.flickr.com/photos/marsi/2300536681/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2279/2300536681_586f83830a_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
504
|
+
|
505
|
+
</description>
|
506
|
+
<pubDate>Fri, 29 Feb 2008 17:06:03 -0800</pubDate>
|
507
|
+
<dc:date.Taken>2008-02-28T19:37:04-08:00</dc:date.Taken>
|
508
|
+
<author flickr:profile="http://www.flickr.com/people/marsi/">nobody@flickr.com (marsi)</author>
|
509
|
+
<guid isPermaLink="false">tag:flickr.com,2004:/photo/2300536681</guid>
|
510
|
+
<media:content url="http://farm3.static.flickr.com/2279/2300536681_2f9a1350ea_o.jpg"
|
511
|
+
type="image/jpeg"
|
512
|
+
height="1500"
|
513
|
+
width="2000"/>
|
514
|
+
<media:title>Passing the Boot</media:title>
|
515
|
+
<media:text type="html"><p><a href="http://www.flickr.com/people/marsi/">marsi</a> posted a photo:</p>
|
516
|
+
<p><a href="http://www.flickr.com/photos/marsi/2300536681/" title="Passing the Boot"><img src="http://farm3.static.flickr.com/2279/2300536681_586f83830a_m.jpg" width="240" height="180" alt="Passing the Boot" /></a></p>
|
517
|
+
|
518
|
+
</media:text>
|
519
|
+
<media:thumbnail url="http://farm3.static.flickr.com/2279/2300536681_586f83830a_s.jpg" height="75" width="75" />
|
520
|
+
<media:credit role="photographer">marsi</media:credit>
|
521
|
+
<media:category scheme="urn:flickr:tags">sanfrancisco beer drinking german suppenkuche</media:category>
|
522
|
+
|
523
|
+
</item>
|
524
|
+
|
525
|
+
</channel>
|
526
|
+
</rss>
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/kind_dom'
|
3
|
+
|
4
|
+
class KindDomTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
@@test_dom = KindDom.new(File.read(File.dirname(__FILE__) + '/flickr_rss.xml'))
|
7
|
+
|
8
|
+
def test_dom_initialization
|
9
|
+
assert_kind_of XML::Document, @@test_dom
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def test_content_for__success
|
14
|
+
assert_equal 'Photos from marsi', @@test_dom.content_for('channel/title')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_content_for__success_with_closure
|
18
|
+
assert_equal 'PHOTOS FROM MARSI', @@test_dom.content_for('channel/title') {|content| content.upcase}
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_content_for__default
|
22
|
+
assert_equal 'a flickr stream', @@test_dom.content_for('//blank_or_non_existent', 'a flickr stream')
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_content_for__default_with_closure
|
26
|
+
assert_equal 'A FLICKR STREAM', @@test_dom.content_for('//blank_or_non_existent', 'a flickr stream') {|content| content.upcase}
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_content_for__failure
|
30
|
+
assert_nil @@test_dom.content_for('//blank_or_non_existent')
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_content_for__failure_with_closure
|
34
|
+
assert_nil @@test_dom.content_for('//blank_or_non_existent') {|content| 'this closure is not called'}
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def test_collection_of__success
|
39
|
+
items = @@test_dom.collection_of('channel/item')
|
40
|
+
assert_kind_of Enumerable, items
|
41
|
+
assert 20 == items.size
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_collection_of__success_with_closure
|
45
|
+
items = @@test_dom.collection_of('channel/item') {|collection| collection[0..-2]}
|
46
|
+
assert_kind_of Enumerable, items
|
47
|
+
assert 19 == items.size
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_collection_of__default
|
51
|
+
items = @@test_dom.collection_of('//blank_or_non_existent', ['A lonely default item'])
|
52
|
+
assert_kind_of Enumerable, items
|
53
|
+
assert 1 == items.size
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_collection_of__default_with_closure
|
57
|
+
items = @@test_dom.collection_of('//blank_or_non_existent', Array.new) {|collection| collection << 'I was empty' }
|
58
|
+
assert_kind_of Enumerable, items
|
59
|
+
assert 1 == items.size
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_collection_of__failure
|
63
|
+
assert_nil @@test_dom.collection_of('//blank_or_non_existent')
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_collection_of__failure_with_closure
|
67
|
+
assert_nil @@test_dom.collection_of('//blank_or_non_existent') {|collection| 'this closure is not called'}
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def test_first_of__success
|
72
|
+
assert_kind_of XML::Node, @@test_dom.first_of('channel/item')
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_first_of__success_with_closure
|
76
|
+
n = @@test_dom.first_of('channel/item') {|node| node.parent}
|
77
|
+
assert_kind_of XML::Node, n
|
78
|
+
assert_equal 'channel', n.name
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_first_of__failure
|
82
|
+
assert_nil @@test_dom.first_of('//blank_or_non_existent')
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_first_of__failure_with_closure
|
86
|
+
assert_nil @@test_dom.first_of('//blank_or_non_existent') {|node| 'this closure is not called'}
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kind_dom
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mars Hall
|
8
|
+
autorequire: kind_dom
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-04-07 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: object_proxy
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.2
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: activesupport
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 2.0.2
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: libxml-ruby
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.5.2.0
|
41
|
+
version:
|
42
|
+
description:
|
43
|
+
email: mars@scoutlabs.com
|
44
|
+
executables: []
|
45
|
+
|
46
|
+
extensions: []
|
47
|
+
|
48
|
+
extra_rdoc_files:
|
49
|
+
- README
|
50
|
+
files:
|
51
|
+
- lib/kind_dom.rb
|
52
|
+
- test/flickr_rss.xml
|
53
|
+
- test/kind_dom_test.rb
|
54
|
+
- README
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: http://code.google.com/p/ruby-kind-dom/
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project: kind-dom
|
77
|
+
rubygems_version: 1.0.1
|
78
|
+
signing_key:
|
79
|
+
specification_version: 2
|
80
|
+
summary: Gracefully use XML content with node-type neutrality, content closure & default values
|
81
|
+
test_files:
|
82
|
+
- test/kind_dom_test.rb
|