KindDom 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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.
@@ -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
@@ -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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
24
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2355265931/&quot; title=&quot;Alaya Cove&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2152/2355265931_c1750f4f82_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Alaya Cove&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
25
+
26
+ &lt;p&gt;at Angel Island, the ferry landing&lt;/p&gt;</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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
37
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2355265931/&quot; title=&quot;Alaya Cove&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2152/2355265931_c1750f4f82_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Alaya Cove&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
38
+
39
+ &lt;p&gt;at Angel Island, the ferry landing&lt;/p&gt;</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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
49
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356098262/&quot; title=&quot;stained glass paper bag&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3012/2356098262_40ffffbabc_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;stained glass paper bag&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
50
+
51
+ &lt;p&gt;a paper bag previously full of buttery shortbread&lt;/p&gt;</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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
62
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356098262/&quot; title=&quot;stained glass paper bag&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3012/2356098262_40ffffbabc_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;stained glass paper bag&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
63
+
64
+ &lt;p&gt;a paper bag previously full of buttery shortbread&lt;/p&gt;</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>&quot;dive in&quot;</title>
71
+ <link>http://www.flickr.com/photos/marsi/2356097566/</link>
72
+ <description>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
73
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356097566/&quot; title=&quot;&amp;quot;dive in&amp;quot;&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2316/2356097566_c2c293bbca_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;&amp;quot;dive in&amp;quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
74
+
75
+ &lt;p&gt;if only I were a bumble bee&lt;/p&gt;</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>&quot;dive in&quot;</media:title>
85
+ <media:text type="html">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
86
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356097566/&quot; title=&quot;&amp;quot;dive in&amp;quot;&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2316/2356097566_c2c293bbca_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;&amp;quot;dive in&amp;quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
87
+
88
+ &lt;p&gt;if only I were a bumble bee&lt;/p&gt;</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 &amp; Josh</title>
96
+ <link>http://www.flickr.com/photos/marsi/2355263497/</link>
97
+ <description>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
98
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2355263497/&quot; title=&quot;Graham &amp;amp; Josh&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3289/2355263497_5b19703602_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Graham &amp;amp; Josh&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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 &amp; Josh</media:title>
110
+ <media:text type="html">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
111
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2355263497/&quot; title=&quot;Graham &amp;amp; Josh&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3289/2355263497_5b19703602_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Graham &amp;amp; Josh&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
123
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356095812/&quot; title=&quot;Northeast view from Angel Island&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2005/2356095812_059dc9dc75_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Northeast view from Angel Island&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
136
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356095812/&quot; title=&quot;Northeast view from Angel Island&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2005/2356095812_059dc9dc75_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Northeast view from Angel Island&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
148
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356094942/&quot; title=&quot;campers settling in&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2389/2356094942_54ba7d6fda_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;campers settling in&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
161
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356094942/&quot; title=&quot;campers settling in&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2389/2356094942_54ba7d6fda_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;campers settling in&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
173
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356094180/&quot; title=&quot;vivid Angel Island flora&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3061/2356094180_929589aa41_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;vivid Angel Island flora&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
186
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2356094180/&quot; title=&quot;vivid Angel Island flora&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3061/2356094180_929589aa41_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;vivid Angel Island flora&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
198
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2355259849/&quot; title=&quot;covert seal observation unit&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3180/2355259849_410df80ffe_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;covert seal observation unit&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
211
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2355259849/&quot; title=&quot;covert seal observation unit&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3180/2355259849_410df80ffe_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;covert seal observation unit&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
223
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2343888675/&quot; title=&quot;WTFBBQMATE&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3087/2343888675_d8e20acb41_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;WTFBBQMATE&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
236
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2343888675/&quot; title=&quot;WTFBBQMATE&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3087/2343888675_d8e20acb41_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;WTFBBQMATE&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
247
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2344716850/&quot; title=&quot;St. Patricks Day&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2334/2344716850_fc105cfbbe_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;St. Patricks Day&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
248
+
249
+ &lt;p&gt;with Bob &amp;amp; Tony&lt;/p&gt;</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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
260
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2344716850/&quot; title=&quot;St. Patricks Day&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2334/2344716850_fc105cfbbe_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;St. Patricks Day&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
261
+
262
+ &lt;p&gt;with Bob &amp;amp; Tony&lt;/p&gt;</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 &amp; pepper</title>
270
+ <link>http://www.flickr.com/photos/marsi/2338452559/</link>
271
+ <description>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
272
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2338452559/&quot; title=&quot;my salt &amp;amp; pepper&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2034/2338452559_a4ba730701_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;my salt &amp;amp; pepper&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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 &amp; pepper</media:title>
284
+ <media:text type="html">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
285
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2338452559/&quot; title=&quot;my salt &amp;amp; pepper&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2034/2338452559_a4ba730701_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;my salt &amp;amp; pepper&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
297
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2339284670/&quot; title=&quot;self-service haircut&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2328/2339284670_a27417ac58_m.jpg&quot; width=&quot;240&quot; height=&quot;192&quot; alt=&quot;self-service haircut&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
310
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2339284670/&quot; title=&quot;self-service haircut&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2328/2339284670_a27417ac58_m.jpg&quot; width=&quot;240&quot; height=&quot;192&quot; alt=&quot;self-service haircut&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
322
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2323742185/&quot; title=&quot;Last Climb&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3146/2323742185_143bae8d27_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Last Climb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
323
+
324
+ &lt;p&gt;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).&lt;/p&gt;</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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
335
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2323742185/&quot; title=&quot;Last Climb&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3146/2323742185_143bae8d27_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Last Climb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
336
+
337
+ &lt;p&gt;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).&lt;/p&gt;</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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
347
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2321598135/&quot; title=&quot;Zinger in SF&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2050/2321598135_fb3c8b93fa_m.jpg&quot; width=&quot;240&quot; height=&quot;100&quot; alt=&quot;Zinger in SF&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
348
+
349
+ &lt;p&gt;Exploratory route through town on the new road cycle.&lt;br /&gt;
350
+ &lt;a href=&quot;http://www.gmap-pedometer.com/?r=1686260&quot;&gt;www.gmap-pedometer.com/?r=1686260&lt;/a&gt;&lt;br /&gt;
351
+ &lt;br /&gt;
352
+ 21-miles; 700' of climb.&lt;/p&gt;</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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
363
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2321598135/&quot; title=&quot;Zinger in SF&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2050/2321598135_fb3c8b93fa_m.jpg&quot; width=&quot;240&quot; height=&quot;100&quot; alt=&quot;Zinger in SF&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
364
+
365
+ &lt;p&gt;Exploratory route through town on the new road cycle.&lt;br /&gt;
366
+ &lt;a href=&quot;http://www.gmap-pedometer.com/?r=1686260&quot;&gt;www.gmap-pedometer.com/?r=1686260&lt;/a&gt;&lt;br /&gt;
367
+ &lt;br /&gt;
368
+ 21-miles; 700' of climb.&lt;/p&gt;</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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
378
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2303163814/&quot; title=&quot;Lock it or loose it.&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2179/2303163814_f586f7c5f0_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Lock it or loose it.&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
379
+
380
+ &lt;p&gt;@ Divisidero &amp;amp; Fell; fortunately not my bike&lt;/p&gt;</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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
391
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2303163814/&quot; title=&quot;Lock it or loose it.&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2179/2303163814_f586f7c5f0_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Lock it or loose it.&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
392
+
393
+ &lt;p&gt;@ Divisidero &amp;amp; Fell; fortunately not my bike&lt;/p&gt;</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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
403
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2301330236/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2113/2301330236_16231499f5_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
416
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2301330236/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2113/2301330236_16231499f5_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
428
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2301330214/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3001/2301330214_6b371825b3_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
441
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2301330214/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3001/2301330214_6b371825b3_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
453
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2301330182/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2396/2301330182_571e7ef1e7_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
466
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2301330182/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2396/2301330182_571e7ef1e7_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
478
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2300536709/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2335/2300536709_c4fe028bb0_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
491
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2300536709/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2335/2300536709_c4fe028bb0_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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>&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
503
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2300536681/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2279/2300536681_586f83830a_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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">&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/people/marsi/&quot;&gt;marsi&lt;/a&gt; posted a photo:&lt;/p&gt;
516
+ &lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/marsi/2300536681/&quot; title=&quot;Passing the Boot&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2279/2300536681_586f83830a_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; alt=&quot;Passing the Boot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
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: KindDom
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Mars Hall
8
+ autorequire: kind_dom
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-04-06 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