feedtools 0.2.22 → 0.2.23

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,140 +21,18 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
+ require 'feed_tools/feed_structures'
25
+
24
26
  module FeedTools
25
27
  # The <tt>FeedTools::FeedItem</tt> class represents the structure of
26
28
  # a single item within a web feed.
27
29
  class FeedItem
28
- # :stopdoc:
29
- include REXML
30
- include GenericHelper
31
- private :validate_options
32
- # :startdoc:
33
-
34
- # This class stores information about a feed item's file enclosures.
35
- class Enclosure
36
- # The url for the enclosure
37
- attr_accessor :url
38
- # The MIME type of the file referenced by the enclosure
39
- attr_accessor :type
40
- # The size of the file referenced by the enclosure
41
- attr_accessor :file_size
42
- # The total play time of the file referenced by the enclosure
43
- attr_accessor :duration
44
- # The height in pixels of the enclosed media
45
- attr_accessor :height
46
- # The width in pixels of the enclosed media
47
- attr_accessor :width
48
- # The bitrate of the enclosed media
49
- attr_accessor :bitrate
50
- # The framerate of the enclosed media
51
- attr_accessor :framerate
52
- # The thumbnail for this enclosure
53
- attr_accessor :thumbnail
54
- # The categories for this enclosure
55
- attr_accessor :categories
56
- # A hash of the enclosed file
57
- attr_accessor :hash
58
- # A website containing some kind of media player instead of a direct
59
- # link to the media file.
60
- attr_accessor :player
61
- # A list of credits for the enclosed media
62
- attr_accessor :credits
63
- # A text rendition of the enclosed media
64
- attr_accessor :text
65
- # A list of alternate version of the enclosed media file
66
- attr_accessor :versions
67
- # The default version of the enclosed media file
68
- attr_accessor :default_version
69
-
70
- # Returns true if this is the default enclosure
71
- def is_default?
72
- return @is_default
73
- end
74
-
75
- # Sets whether this is the default enclosure for the media group
76
- def is_default=(new_is_default)
77
- @is_default = new_is_default
78
- end
79
-
80
- # Returns true if the enclosure contains explicit material
81
- def explicit?
82
- return @explicit
83
- end
84
-
85
- # Sets the explicit attribute on the enclosure
86
- def explicit=(new_explicit)
87
- @explicit = new_explicit
88
- end
89
-
90
- # Determines if the object is a sample, or the full version of the
91
- # object, or if it is a stream.
92
- # Possible values are 'sample', 'full', 'nonstop'.
93
- def expression
94
- return @expression
95
- end
96
-
97
- # Sets the expression attribute on the enclosure.
98
- # Allowed values are 'sample', 'full', 'nonstop'.
99
- def expression=(new_expression)
100
- unless ['sample', 'full', 'nonstop'].include? new_expression.downcase
101
- raise ArgumentError,
102
- "Permitted values are 'sample', 'full', 'nonstop'."
103
- end
104
- @expression = new_expression.downcase
105
- end
106
-
107
- # Returns true if this enclosure contains audio content
108
- def audio?
109
- unless self.type.nil?
110
- return true if (self.type =~ /^audio/) != nil
111
- end
112
- # TODO: create a more complete list
113
- # =================================
114
- audio_extensions = ['mp3', 'm4a', 'm4p', 'wav', 'ogg', 'wma']
115
- audio_extensions.each do |extension|
116
- if (url =~ /#{extension}$/) != nil
117
- return true
118
- end
119
- end
120
- return false
121
- end
122
-
123
- # Returns true if this enclosure contains video content
124
- def video?
125
- unless self.type.nil?
126
- return true if (self.type =~ /^video/) != nil
127
- return true if self.type == "image/mov"
128
- end
129
- # TODO: create a more complete list
130
- # =================================
131
- video_extensions = ['mov', 'mp4', 'avi', 'wmv', 'asf']
132
- video_extensions.each do |extension|
133
- if (url =~ /#{extension}$/) != nil
134
- return true
135
- end
136
- end
137
- return false
138
- end
139
-
140
- alias_method :link, :url
141
- alias_method :link=, :url=
142
- end
143
-
144
- # TODO: Make these actual classes instead of structs
145
- # ==================================================
146
- EnclosureHash = Struct.new( "EnclosureHash", :hash, :type )
147
- EnclosurePlayer = Struct.new( "EnclosurePlayer", :url, :height, :width )
148
- EnclosureCredit = Struct.new( "EnclosureCredit", :name, :role )
149
- EnclosureThumbnail = Struct.new( "EnclosureThumbnail", :url, :height,
150
- :width )
151
-
152
30
  # Initialize the feed object
153
31
  def initialize
154
32
  super
155
33
  @feed_data = nil
156
34
  @feed_data_type = :xml
157
- @xml_doc = nil
35
+ @xml_document = nil
158
36
  @root_node = nil
159
37
  @title = nil
160
38
  @id = nil
@@ -191,6 +69,14 @@ module FeedTools
191
69
  return parent_feed
192
70
  end
193
71
 
72
+ # Returns the feed item's encoding.
73
+ def encoding
74
+ if @encoding.nil?
75
+ @encoding = self.feed.encoding
76
+ end
77
+ return @encoding
78
+ end
79
+
194
80
  # Returns the feed item's raw data.
195
81
  def feed_data
196
82
  return @feed_data
@@ -213,18 +99,18 @@ module FeedTools
213
99
  end
214
100
 
215
101
  # Returns a REXML Document of the feed_data
216
- def xml
102
+ def xml_document
217
103
  if self.feed_data_type != :xml
218
- @xml_doc = nil
104
+ @xml_document = nil
219
105
  else
220
- if @xml_doc.nil?
106
+ if @xml_document.nil?
221
107
  # TODO: :ignore_whitespace_nodes => :all
222
108
  # Add that?
223
109
  # ======================================
224
- @xml_doc = Document.new(self.feed_data)
110
+ @xml_document = REXML::Document.new(self.feed_data)
225
111
  end
226
112
  end
227
- return @xml_doc
113
+ return @xml_document
228
114
  end
229
115
 
230
116
  # Returns the first node within the root_node that matches the xpath query.
@@ -232,7 +118,7 @@ module FeedTools
232
118
  if feed.feed_data_type != :xml
233
119
  raise "The feed data type is not xml."
234
120
  end
235
- return try_xpaths(self.root_node, [xpath],
121
+ return FeedTools::XmlHelper.try_xpaths(self.root_node, [xpath],
236
122
  :select_result_value => select_result_value)
237
123
  end
238
124
 
@@ -241,25 +127,52 @@ module FeedTools
241
127
  if feed.feed_data_type != :xml
242
128
  raise "The feed data type is not xml."
243
129
  end
244
- return try_xpaths_all(self.root_node, [xpath],
130
+ return FeedTools::XmlHelper.try_xpaths_all(self.root_node, [xpath],
245
131
  :select_result_value => select_result_value)
246
132
  end
247
133
 
248
134
  # Returns the root node of the feed item.
249
135
  def root_node
250
136
  if @root_node.nil?
251
- if xml.nil?
137
+ if self.xml_document.nil?
252
138
  return nil
253
139
  end
254
- @root_node = xml.root
140
+ @root_node = self.xml_document.root
255
141
  end
256
142
  return @root_node
257
143
  end
144
+
145
+ # Sets the root node of the feed item.
146
+ #
147
+ # This allows namespace information to be inherited by the feed item
148
+ # from the feed itself. When creating individual nodes from scratch,
149
+ # the <tt>feed_data=</tt> method should be used instead.
150
+ def root_node=(new_root_node)
151
+ @root_node = new_root_node
152
+ end
153
+
154
+ # Returns the feed type of this item
155
+ def feed_type
156
+ if @feed_type.nil?
157
+ parent_feed = self.feed
158
+ @feed_type = parent_feed.feed_type unless parent_feed.nil?
159
+ end
160
+ return @feed_type
161
+ end
162
+
163
+ # Returns the feed version of this item
164
+ def feed_version
165
+ if @feed_version.nil?
166
+ parent_feed = self.feed
167
+ @feed_version = parent_feed.feed_version unless parent_feed.nil?
168
+ end
169
+ return @feed_version
170
+ end
258
171
 
259
172
  # Returns the feed items's unique id
260
173
  def id
261
174
  if @id.nil?
262
- @id = try_xpaths(self.root_node, [
175
+ @id = FeedTools::XmlHelper.try_xpaths(self.root_node, [
263
176
  "atom10:id/text()",
264
177
  "atom03:id/text()",
265
178
  "atom:id/text()",
@@ -279,42 +192,18 @@ module FeedTools
279
192
  def title
280
193
  if @title.nil?
281
194
  repair_entities = false
282
- title_node = try_xpaths(self.root_node, [
195
+ title_node = FeedTools::XmlHelper.try_xpaths(self.root_node, [
283
196
  "atom10:title",
284
197
  "atom03:title",
285
198
  "atom:title",
286
199
  "title",
287
200
  "dc:title"
288
201
  ])
289
- if title_node.nil?
290
- return nil
291
- end
292
- title_type = try_xpaths(title_node, "@type",
293
- :select_result_value => true)
294
- title_mode = try_xpaths(title_node, "@mode",
295
- :select_result_value => true)
296
- title_encoding = try_xpaths(title_node, "@encoding",
297
- :select_result_value => true)
298
-
299
- # Note that we're checking for misuse of type, mode and encoding here
300
- if title_type == "base64" || title_mode == "base64" ||
301
- title_encoding == "base64"
302
- @title = Base64.decode64(title_node.inner_xml.strip)
303
- elsif title_type == "xhtml" || title_mode == "xhtml" ||
304
- title_type == "xml" || title_mode == "xml" ||
305
- title_type == "application/xhtml+xml"
306
- @title = title_node.inner_xml
307
- elsif title_type == "escaped" || title_mode == "escaped"
308
- @title = FeedTools.unescape_entities(
309
- title_node.inner_xml)
310
- else
311
- @title = title_node.inner_xml
312
- repair_entities = true
313
- end
314
- unless @title.nil?
315
- @title = FeedTools.sanitize_html(@title, :strip)
316
- @title = FeedTools.unescape_entities(@title) if repair_entities
317
- @title = FeedTools.tidy_html(@title) unless repair_entities
202
+ @title = FeedTools::HtmlHelper.process_text_construct(title_node,
203
+ self.feed_type, self.feed_version)
204
+ if self.feed_type == "atom" ||
205
+ FeedTools.configurations[:always_strip_wrapper_elements]
206
+ @title = FeedTools::HtmlHelper.strip_wrapper_element(@title)
318
207
  end
319
208
  if !@title.blank? && FeedTools.configurations[:strip_comment_count]
320
209
  # Some blogging tools include the number of comments in a post
@@ -326,9 +215,6 @@ module FeedTools
326
215
  # unstripped title, just use find_node("title/text()").to_s
327
216
  @title = @title.strip.gsub(/\[\d*\]$/, "").strip
328
217
  end
329
- @title.gsub!(/>\n</, "><")
330
- @title.gsub!(/\n/, " ")
331
- @title.strip!
332
218
  @title = nil if @title.blank?
333
219
  end
334
220
  return @title
@@ -343,15 +229,19 @@ module FeedTools
343
229
  def content
344
230
  if @content.nil?
345
231
  repair_entities = false
346
- content_node = try_xpaths(self.root_node, [
232
+ content_node = FeedTools::XmlHelper.try_xpaths(self.root_node, [
347
233
  "atom10:content",
348
234
  "atom03:content",
349
235
  "atom:content",
236
+ "xhtml:body",
237
+ "body",
238
+ "xhtml:div",
239
+ "div",
240
+ "p:payload",
241
+ "payload",
350
242
  "content:encoded",
351
243
  "content",
352
244
  "fullitem",
353
- "xhtml:body",
354
- "body",
355
245
  "encoded",
356
246
  "description",
357
247
  "tagline",
@@ -364,35 +254,14 @@ module FeedTools
364
254
  "blurb",
365
255
  "info"
366
256
  ])
367
- if content_node.nil?
368
- return nil
257
+ @content = FeedTools::HtmlHelper.process_text_construct(content_node,
258
+ self.feed_type, self.feed_version)
259
+ if self.feed_type == "atom" ||
260
+ FeedTools.configurations[:always_strip_wrapper_elements]
261
+ @content = FeedTools::HtmlHelper.strip_wrapper_element(@content)
369
262
  end
370
- content_type = try_xpaths(content_node, "@type",
371
- :select_result_value => true)
372
- content_mode = try_xpaths(content_node, "@mode",
373
- :select_result_value => true)
374
- content_encoding = try_xpaths(content_node, "@encoding",
375
- :select_result_value => true)
376
-
377
- # Note that we're checking for misuse of type, mode and encoding here
378
- if !content_encoding.blank?
379
- @content =
380
- "[Embedded data objects are not currently supported.]"
381
- elsif content_node.cdatas.size > 0
382
- @content = content_node.cdatas.first.value
383
- elsif content_type == "base64" || content_mode == "base64" ||
384
- content_encoding == "base64"
385
- @content = Base64.decode64(content_node.inner_xml.strip)
386
- elsif content_type == "xhtml" || content_mode == "xhtml" ||
387
- content_type == "xml" || content_mode == "xml" ||
388
- content_type == "application/xhtml+xml"
389
- @content = content_node.inner_xml
390
- elsif content_type == "escaped" || content_mode == "escaped"
391
- @content = FeedTools.unescape_entities(
392
- content_node.inner_xml)
393
- else
394
- @content = content_node.inner_xml
395
- repair_entities = true
263
+ if @content.blank?
264
+ @content = self.media_text
396
265
  end
397
266
  if @content.blank?
398
267
  @content = self.itunes_summary
@@ -400,15 +269,6 @@ module FeedTools
400
269
  if @content.blank?
401
270
  @content = self.itunes_subtitle
402
271
  end
403
-
404
- unless @content.blank?
405
- @content = FeedTools.sanitize_html(@content, :strip)
406
- @content = FeedTools.unescape_entities(@content) if repair_entities
407
- @content = FeedTools.tidy_html(@content)
408
- end
409
-
410
- @content = @content.strip unless @content.nil?
411
- @content = nil if @content.blank?
412
272
  end
413
273
  return @content
414
274
  end
@@ -422,7 +282,7 @@ module FeedTools
422
282
  def summary
423
283
  if @summary.nil?
424
284
  repair_entities = false
425
- summary_node = try_xpaths(self.root_node, [
285
+ summary_node = FeedTools::XmlHelper.try_xpaths(self.root_node, [
426
286
  "atom10:summary",
427
287
  "atom03:summary",
428
288
  "atom:summary",
@@ -432,9 +292,13 @@ module FeedTools
432
292
  "description",
433
293
  "tagline",
434
294
  "subtitle",
435
- "fullitem",
436
295
  "xhtml:body",
437
296
  "body",
297
+ "xhtml:div",
298
+ "div",
299
+ "p:payload",
300
+ "payload",
301
+ "fullitem",
438
302
  "content:encoded",
439
303
  "encoded",
440
304
  "atom10:content",
@@ -443,35 +307,14 @@ module FeedTools
443
307
  "content",
444
308
  "info"
445
309
  ])
446
- if summary_node.nil?
447
- return nil
310
+ @summary = FeedTools::HtmlHelper.process_text_construct(summary_node,
311
+ self.feed_type, self.feed_version)
312
+ if self.feed_type == "atom" ||
313
+ FeedTools.configurations[:always_strip_wrapper_elements]
314
+ @summary = FeedTools::HtmlHelper.strip_wrapper_element(@summary)
448
315
  end
449
- summary_type = try_xpaths(summary_node, "@type",
450
- :select_result_value => true)
451
- summary_mode = try_xpaths(summary_node, "@mode",
452
- :select_result_value => true)
453
- summary_encoding = try_xpaths(summary_node, "@encoding",
454
- :select_result_value => true)
455
-
456
- # Note that we're checking for misuse of type, mode and encoding here
457
- if !summary_encoding.blank?
458
- @summary =
459
- "[Embedded data objects are not currently supported.]"
460
- elsif summary_node.cdatas.size > 0
461
- @summary = summary_node.cdatas.first.value
462
- elsif summary_type == "base64" || summary_mode == "base64" ||
463
- summary_encoding == "base64"
464
- @summary = Base64.decode64(summary_node.inner_xml.strip)
465
- elsif summary_type == "xhtml" || summary_mode == "xhtml" ||
466
- summary_type == "xml" || summary_mode == "xml" ||
467
- summary_type == "application/xhtml+xml"
468
- @summary = summary_node.inner_xml
469
- elsif summary_type == "escaped" || summary_mode == "escaped"
470
- @summary = FeedTools.unescape_entities(
471
- summary_node.inner_xml)
472
- else
473
- @summary = summary_node.inner_xml
474
- repair_entities = true
316
+ if @summary.blank?
317
+ @summary = self.media_text
475
318
  end
476
319
  if @summary.blank?
477
320
  @summary = self.itunes_summary
@@ -479,15 +322,6 @@ module FeedTools
479
322
  if @summary.blank?
480
323
  @summary = self.itunes_subtitle
481
324
  end
482
-
483
- unless @summary.blank?
484
- @summary = FeedTools.sanitize_html(@summary, :strip)
485
- @summary = FeedTools.unescape_entities(@summary) if repair_entities
486
- @summary = FeedTools.tidy_html(@summary)
487
- end
488
-
489
- @summary = @summary.strip unless @summary.nil?
490
- @summary = nil if @summary.blank?
491
325
  end
492
326
  return @summary
493
327
  end
@@ -500,12 +334,13 @@ module FeedTools
500
334
  # Returns the contents of the itunes:summary element
501
335
  def itunes_summary
502
336
  if @itunes_summary.nil?
503
- @itunes_summary = try_xpaths(self.root_node, [
337
+ @itunes_summary = FeedTools::XmlHelper.try_xpaths(self.root_node, [
504
338
  "itunes:summary/text()"
505
- ])
339
+ ], :select_result_value => true)
506
340
  unless @itunes_summary.blank?
507
- @itunes_summary = FeedTools.unescape_entities(@itunes_summary)
508
- @itunes_summary = FeedTools.sanitize_html(@itunes_summary)
341
+ @itunes_summary = FeedTools::HtmlHelper.unescape_entities(@itunes_summary)
342
+ @itunes_summary = FeedTools::HtmlHelper.sanitize_html(@itunes_summary)
343
+ @itunes_summary.strip!
509
344
  else
510
345
  @itunes_summary = nil
511
346
  end
@@ -521,12 +356,13 @@ module FeedTools
521
356
  # Returns the contents of the itunes:subtitle element
522
357
  def itunes_subtitle
523
358
  if @itunes_subtitle.nil?
524
- @itunes_subtitle = try_xpaths(self.root_node, [
359
+ @itunes_subtitle = FeedTools::XmlHelper.try_xpaths(self.root_node, [
525
360
  "itunes:subtitle/text()"
526
- ])
361
+ ], :select_result_value => true)
527
362
  unless @itunes_subtitle.blank?
528
- @itunes_subtitle = FeedTools.unescape_entities(@itunes_subtitle)
529
- @itunes_subtitle = FeedTools.sanitize_html(@itunes_subtitle)
363
+ @itunes_subtitle = FeedTools::HtmlHelper.unescape_entities(@itunes_subtitle)
364
+ @itunes_subtitle = FeedTools::HtmlHelper.sanitize_html(@itunes_subtitle)
365
+ @itunes_subtitle.strip!
530
366
  else
531
367
  @itunes_subtitle = nil
532
368
  end
@@ -542,14 +378,16 @@ module FeedTools
542
378
  # Returns the contents of the media:text element
543
379
  def media_text
544
380
  if @media_text.nil?
545
- @media_text = FeedTools.unescape_entities(XPath.first(root_node,
546
- "itunes:subtitle/text()").to_s)
547
- if @media_text == ""
381
+ @media_text = FeedTools::XmlHelper.try_xpaths(self.root_node, [
382
+ "media:text/text()"
383
+ ], :select_result_value => true)
384
+ unless @media_text.blank?
385
+ @media_text = FeedTools::HtmlHelper.unescape_entities(@media_text)
386
+ @media_text = FeedTools::HtmlHelper.sanitize_html(@media_text)
387
+ @media_text.strip!
388
+ else
548
389
  @media_text = nil
549
390
  end
550
- unless @media_text.nil?
551
- @media_text = FeedTools.sanitize_html(@media_text)
552
- end
553
391
  end
554
392
  return @media_text
555
393
  end
@@ -562,88 +400,64 @@ module FeedTools
562
400
  # Returns the feed item link
563
401
  def link
564
402
  if @link.nil?
565
- @link = try_xpaths(self.root_node, [
566
- "atom10:link[@type='application/xhtml+xml']/@href",
567
- "atom10:link[@type='text/html']/@href",
568
- "atom10:link[@rel='alternate']/@href",
569
- "atom03:link[@type='application/xhtml+xml']/@href",
570
- "atom03:link[@type='text/html']/@href",
571
- "atom03:link[@rel='alternate']/@href",
572
- "atom:link[@type='application/xhtml+xml']/@href",
573
- "atom:link[@type='text/html']/@href",
574
- "atom:link[@rel='alternate']/@href",
575
- "link[@type='application/xhtml+xml']/@href",
576
- "link[@type='text/html']/@href",
577
- "link[@rel='alternate']/@href",
578
- "link/text()",
579
- "@rdf:about",
580
- "guid[@isPermaLink='true']/text()",
581
- "@href",
582
- "a/@href"
583
- ], :select_result_value => true)
403
+ max_score = 0
404
+ for link_object in self.links.reverse
405
+ score = 0
406
+ if FeedTools::HtmlHelper.html_type?(link_object.type)
407
+ score = score + 2
408
+ elsif link_object.type != nil
409
+ score = score - 1
410
+ end
411
+ if FeedTools::HtmlHelper.xml_type?(link_object.type)
412
+ score = score + 1
413
+ end
414
+ if link_object.rel == "alternate"
415
+ score = score + 1
416
+ end
417
+ if link_object.rel == "self"
418
+ score = score - 1
419
+ end
420
+ if score >= max_score
421
+ max_score = score
422
+ @link = link_object.href
423
+ end
424
+ end
425
+ if @link.blank?
426
+ @link = FeedTools::XmlHelper.try_xpaths(self.root_node, [
427
+ "@href",
428
+ "@rdf:about",
429
+ "@about"
430
+ ], :select_result_value => true)
431
+ end
584
432
  if @link.blank?
585
- if FeedTools.is_uri?(self.guid) &&
586
- !(self.guid =~ /^urn:uuid:/) &&
587
- !(self.guid =~ /^tag:/)
588
- @link = self.guid
433
+ if FeedTools::UriHelper.is_uri?(self.id) &&
434
+ (self.id =~ /^http/)
435
+ @link = self.id
589
436
  end
590
437
  end
591
438
  if !@link.blank?
592
- @link = FeedTools.unescape_entities(@link)
593
- end
594
- # TODO: Actually implement proper relative url resolving instead of this crap
595
- # ===========================================================================
596
- #
597
- # if @link != "" && (@link =~ /http:\/\//) != 0 && (@link =~ /https:\/\//) != 0
598
- # if (feed.base[-1..-1] == "/" && @link[0..0] == "/")
599
- # @link = @link[1..-1]
600
- # end
601
- # # prepend the base to the link since they seem to have used a relative path
602
- # @link = feed.base + @link
603
- # end
604
- if @link.blank?
605
- link_node = try_xpaths(self.root_node, [
606
- "atom10:link",
607
- "atom03:link",
608
- "atom:link",
609
- "link"
610
- ])
611
- if link_node != nil
612
- if link_node.attributes['type'].to_s =~ /^image/ ||
613
- link_node.attributes['type'].to_s =~ /^application/ ||
614
- link_node.attributes['type'].to_s =~ /xml/ ||
615
- link_node.attributes['rel'].to_s =~ /self/
616
- for child in self.root_node
617
- if child.class == REXML::Element
618
- if child.name.downcase == "link"
619
- if child.attributes['type'].to_s =~ /^image/ ||
620
- child.attributes['type'].to_s =~ /^application/ ||
621
- child.attributes['type'].to_s =~ /xml/ ||
622
- child.attributes['rel'].to_s =~ /self/
623
- @link = nil
624
- next
625
- else
626
- @link = child.attributes['href'].to_s
627
- if @link.blank?
628
- @link = child.inner_xml
629
- end
630
- if @link.blank?
631
- next
632
- end
633
- break
634
- end
635
- end
636
- end
439
+ @link = FeedTools::HtmlHelper.unescape_entities(@link)
440
+ end
441
+ @link = self.comments if @link.blank?
442
+ @link = nil if @link.blank?
443
+ begin
444
+ if !(@link =~ /^file:/) &&
445
+ !FeedTools::UriHelper.is_uri?(@link)
446
+ stored_base_uri =
447
+ FeedTools::GenericHelper.recursion_trap(:feed_link) do
448
+ self.feed.base_uri if self.feed != nil
637
449
  end
638
- else
639
- @link = link_node.attributes['href'].to_s
450
+ root_base_uri = nil
451
+ unless self.root_node.nil?
452
+ root_base_uri = self.root_node.base_uri
640
453
  end
454
+ @link = FeedTools::UriHelper.resolve_relative_uri(
455
+ @link, [root_base_uri,stored_base_uri])
641
456
  end
457
+ rescue
642
458
  end
643
- @link = self.comments if @link.blank?
644
- @link = nil if @link.blank?
645
459
  if FeedTools.configurations[:url_normalization_enabled]
646
- @link = FeedTools.normalize_url(@link)
460
+ @link = FeedTools::UriHelper.normalize_url(@link)
647
461
  end
648
462
  end
649
463
  return @link
@@ -653,24 +467,135 @@ module FeedTools
653
467
  def link=(new_link)
654
468
  @link = new_link
655
469
  end
470
+
471
+ # Returns the links collection
472
+ def links
473
+ if @links.nil?
474
+ @links = []
475
+ link_nodes =
476
+ FeedTools::XmlHelper.combine_xpaths_all(self.root_node, [
477
+ "atom10:link",
478
+ "atom03:link",
479
+ "atom:link",
480
+ "link",
481
+ "a",
482
+ "url",
483
+ "href"
484
+ ])
485
+ for link_node in link_nodes
486
+ link_object = FeedTools::Link.new
487
+ link_object.href = FeedTools::XmlHelper.try_xpaths(link_node, [
488
+ "@atom10:href",
489
+ "@atom03:href",
490
+ "@atom:href",
491
+ "@href",
492
+ "text()"
493
+ ], :select_result_value => true)
494
+ if link_object.href.nil? && link_node.base_uri != nil
495
+ link_object.href = ""
496
+ end
497
+ begin
498
+ if !(link_object.href =~ /^file:/) &&
499
+ !FeedTools::UriHelper.is_uri?(link_object.href)
500
+ stored_base_uri =
501
+ FeedTools::GenericHelper.recursion_trap(:feed_link) do
502
+ self.feed.base_uri if self.feed != nil
503
+ end
504
+ link_object.href = FeedTools::UriHelper.resolve_relative_uri(
505
+ link_object.href,
506
+ [link_node.base_uri, stored_base_uri])
507
+ end
508
+ rescue
509
+ end
510
+ if FeedTools.configurations[:url_normalization_enabled]
511
+ link_object.href =
512
+ FeedTools::UriHelper.normalize_url(link_object.href)
513
+ end
514
+ link_object.href.strip! unless link_object.href.nil?
515
+ next if link_object.href.blank?
516
+ link_object.hreflang = FeedTools::XmlHelper.try_xpaths(link_node, [
517
+ "@atom10:hreflang",
518
+ "@atom03:hreflang",
519
+ "@atom:hreflang",
520
+ "@hreflang"
521
+ ], :select_result_value => true)
522
+ unless link_object.hreflang.nil?
523
+ link_object.hreflang = link_object.hreflang.downcase
524
+ end
525
+ link_object.rel = FeedTools::XmlHelper.try_xpaths(link_node, [
526
+ "@atom10:rel",
527
+ "@atom03:rel",
528
+ "@atom:rel",
529
+ "@rel"
530
+ ], :select_result_value => true)
531
+ unless link_object.rel.nil?
532
+ link_object.rel = link_object.rel.downcase
533
+ end
534
+ link_object.type = FeedTools::XmlHelper.try_xpaths(link_node, [
535
+ "@atom10:type",
536
+ "@atom03:type",
537
+ "@atom:type",
538
+ "@type"
539
+ ], :select_result_value => true)
540
+ unless link_object.type.nil?
541
+ link_object.type = link_object.type.downcase
542
+ end
543
+ link_object.title = FeedTools::XmlHelper.try_xpaths(link_node, [
544
+ "@atom10:title",
545
+ "@atom03:title",
546
+ "@atom:title",
547
+ "@title",
548
+ "text()"
549
+ ], :select_result_value => true)
550
+ # This catches the ambiguities between atom, rss, and cdf
551
+ if link_object.title == link_object.href
552
+ link_object.title = nil
553
+ end
554
+ link_object.length = FeedTools::XmlHelper.try_xpaths(link_node, [
555
+ "@atom10:length",
556
+ "@atom03:length",
557
+ "@atom:length",
558
+ "@length"
559
+ ], :select_result_value => true)
560
+ if !link_object.length.nil?
561
+ link_object.length = link_object.length.to_i
562
+ else
563
+ if !link_object.type.nil? && link_object.type[0..4] != "text" &&
564
+ link_object.type[-3..-1] != "xml" &&
565
+ link_object.href =~ /^http:\/\//
566
+ # Retrieve the length with an http HEAD request
567
+ else
568
+ link_object.length = nil
569
+ end
570
+ end
571
+ @links << link_object
572
+ end
573
+ end
574
+ return @links
575
+ end
576
+
577
+ # Sets the links collection
578
+ def links=(new_links)
579
+ @links = new_links
580
+ end
656
581
 
657
582
  # Returns a list of the feed item's categories
658
583
  def categories
659
584
  if @categories.nil?
660
585
  @categories = []
661
- category_nodes = try_xpaths_all(self.root_node, [
586
+ category_nodes = FeedTools::XmlHelper.try_xpaths_all(self.root_node, [
662
587
  "category",
663
588
  "dc:subject"
664
589
  ])
665
590
  for category_node in category_nodes
666
- category = FeedTools::Feed::Category.new
667
- category.term = try_xpaths(category_node, ["@term", "text()"],
591
+ category = FeedTools::Category.new
592
+ category.term = FeedTools::XmlHelper.try_xpaths(category_node, ["@term", "text()"],
668
593
  :select_result_value => true)
669
594
  category.term.strip! unless category.term.nil?
670
- category.label = try_xpaths(category_node, ["@label"],
595
+ category.label = FeedTools::XmlHelper.try_xpaths(category_node, ["@label"],
671
596
  :select_result_value => true)
672
597
  category.label.strip! unless category.label.nil?
673
- category.scheme = try_xpaths(category_node, [
598
+ category.scheme = FeedTools::XmlHelper.try_xpaths(category_node, [
674
599
  "@scheme",
675
600
  "@domain"
676
601
  ], :select_result_value => true)
@@ -685,57 +610,57 @@ module FeedTools
685
610
  def images
686
611
  if @images.nil?
687
612
  @images = []
688
- image_nodes = try_xpaths_all(self.root_node, [
613
+ image_nodes = FeedTools::XmlHelper.try_xpaths_all(self.root_node, [
689
614
  "image",
690
615
  "logo",
691
616
  "apple-wallpapers:image",
692
- "atom10:link",
693
- "atom03:link",
694
- "atom:link",
695
- "link"
617
+ "imageUrl"
696
618
  ])
697
619
  unless image_nodes.blank?
698
620
  for image_node in image_nodes
699
- image = FeedTools::Feed::Image.new
700
- image.url = try_xpaths(image_node, [
621
+ image = FeedTools::Image.new
622
+ image.href = FeedTools::XmlHelper.try_xpaths(image_node, [
701
623
  "url/text()",
702
624
  "@rdf:resource",
625
+ "@href",
703
626
  "text()"
704
627
  ], :select_result_value => true)
705
- if image.url.blank? && (image_node.name == "logo" ||
706
- (image_node.attributes['type'].to_s =~ /^image/) == 0)
707
- image.url = try_xpaths(image_node, [
708
- "@atom10:href",
709
- "@atom03:href",
710
- "@atom:href",
711
- "@href"
712
- ], :select_result_value => true)
713
- if image.url == self.link && image.url != nil
714
- image.url = nil
715
- end
628
+ if image.href.nil? && image_node.base_uri != nil
629
+ image.href = ""
716
630
  end
717
- if image.url.blank? && image_node.name == "LOGO"
718
- image.url = try_xpaths(image_node, [
719
- "@href"
720
- ], :select_result_value => true)
631
+ begin
632
+ if !(image.href =~ /^file:/) &&
633
+ !FeedTools::UriHelper.is_uri?(image.href)
634
+ stored_base_uri =
635
+ FeedTools::GenericHelper.recursion_trap(:feed_link) do
636
+ self.feed.base_uri if self.feed != nil
637
+ end
638
+ image.href = FeedTools::UriHelper.resolve_relative_uri(
639
+ image.href, [image_node.base_uri, stored_base_uri])
640
+ end
641
+ rescue
721
642
  end
722
- image.url.strip! unless image.url.nil?
723
- image.title = try_xpaths(image_node,
643
+ if FeedTools.configurations[:url_normalization_enabled]
644
+ image.href = FeedTools::UriHelper.normalize_url(image.href)
645
+ end
646
+ image.href.strip! unless image.href.nil?
647
+ next if image.href.blank?
648
+ image.title = FeedTools::XmlHelper.try_xpaths(image_node,
724
649
  ["title/text()"], :select_result_value => true)
725
650
  image.title.strip! unless image.title.nil?
726
- image.description = try_xpaths(image_node,
651
+ image.description = FeedTools::XmlHelper.try_xpaths(image_node,
727
652
  ["description/text()"], :select_result_value => true)
728
653
  image.description.strip! unless image.description.nil?
729
- image.link = try_xpaths(image_node,
654
+ image.link = FeedTools::XmlHelper.try_xpaths(image_node,
730
655
  ["link/text()"], :select_result_value => true)
731
656
  image.link.strip! unless image.link.nil?
732
- image.height = try_xpaths(image_node,
657
+ image.height = FeedTools::XmlHelper.try_xpaths(image_node,
733
658
  ["height/text()"], :select_result_value => true).to_i
734
659
  image.height = nil if image.height <= 0
735
- image.width = try_xpaths(image_node,
660
+ image.width = FeedTools::XmlHelper.try_xpaths(image_node,
736
661
  ["width/text()"], :select_result_value => true).to_i
737
662
  image.width = nil if image.width <= 0
738
- image.style = try_xpaths(image_node, [
663
+ image.style = FeedTools::XmlHelper.try_xpaths(image_node, [
739
664
  "style/text()",
740
665
  "@style"
741
666
  ], :select_result_value => true)
@@ -744,6 +669,14 @@ module FeedTools
744
669
  @images << image unless image.url.nil?
745
670
  end
746
671
  end
672
+ for link_object in self.links
673
+ if link_object.type != nil && link_object.type =~ /^image/
674
+ image = FeedTools::Image.new
675
+ image.href = link_object.href
676
+ image.title = link_object.title
677
+ @images << image unless image.href.nil?
678
+ end
679
+ end
747
680
  end
748
681
  return @images
749
682
  end
@@ -751,12 +684,12 @@ module FeedTools
751
684
  # Returns the feed item itunes image link
752
685
  def itunes_image_link
753
686
  if @itunes_image_link.nil?
754
- @itunes_image_link = try_xpaths(self.root_node, [
687
+ @itunes_image_link = FeedTools::XmlHelper.try_xpaths(self.root_node, [
755
688
  "itunes:image/@href",
756
689
  "itunes:link[@rel='image']/@href"
757
690
  ], :select_result_value => true)
758
691
  if FeedTools.configurations[:url_normalization_enabled]
759
- @itunes_image_link = FeedTools.normalize_url(@itunes_image_link)
692
+ @itunes_image_link = FeedTools::UriHelper.normalize_url(@itunes_image_link)
760
693
  end
761
694
  end
762
695
  return @itunes_image_link
@@ -770,11 +703,11 @@ module FeedTools
770
703
  # Returns the feed item media thumbnail link
771
704
  def media_thumbnail_link
772
705
  if @media_thumbnail_link.nil?
773
- @media_thumbnail_link = try_xpaths(self.root_node, [
706
+ @media_thumbnail_link = FeedTools::XmlHelper.try_xpaths(self.root_node, [
774
707
  "media:thumbnail/@url"
775
708
  ], :select_result_value => true)
776
709
  if FeedTools.configurations[:url_normalization_enabled]
777
- @media_thumbnail_link = FeedTools.normalize_url(@media_thumbnail_link)
710
+ @media_thumbnail_link = FeedTools::UriHelper.normalize_url(@media_thumbnail_link)
778
711
  end
779
712
  end
780
713
  return @media_thumbnail_link
@@ -785,11 +718,11 @@ module FeedTools
785
718
  @media_thumbnail_link = new_media_thumbnail_link
786
719
  end
787
720
 
788
- # Returns the feed item's copyright information
789
- def copyright
790
- if @copyright.nil?
721
+ # Returns the feed item's rights information
722
+ def rights
723
+ if @rights.nil?
791
724
  repair_entities = false
792
- copyright_node = try_xpaths(self.root_node, [
725
+ rights_node = FeedTools::XmlHelper.try_xpaths(self.root_node, [
793
726
  "atom10:copyright",
794
727
  "atom03:copyright",
795
728
  "atom:copyright",
@@ -798,52 +731,27 @@ module FeedTools
798
731
  "dc:rights",
799
732
  "rights"
800
733
  ])
801
- if copyright_node.nil?
802
- return nil
803
- end
804
- copyright_type = try_xpaths(copyright_node, "@type",
805
- :select_result_value => true)
806
- copyright_mode = try_xpaths(copyright_node, "@mode",
807
- :select_result_value => true)
808
- copyright_encoding = try_xpaths(copyright_node, "@encoding",
809
- :select_result_value => true)
810
-
811
- # Note that we're checking for misuse of type, mode and encoding here
812
- if !copyright_encoding.blank?
813
- @copyright =
814
- "[Embedded data objects are not currently supported.]"
815
- elsif copyright_node.cdatas.size > 0
816
- @copyright = copyright_node.cdatas.first.value
817
- elsif copyright_type == "base64" || copyright_mode == "base64" ||
818
- copyright_encoding == "base64"
819
- @copyright = Base64.decode64(copyright_node.inner_xml.strip)
820
- elsif copyright_type == "xhtml" || copyright_mode == "xhtml" ||
821
- copyright_type == "xml" || copyright_mode == "xml" ||
822
- copyright_type == "application/xhtml+xml"
823
- @copyright = copyright_node.inner_xml
824
- elsif copyright_type == "escaped" || copyright_mode == "escaped"
825
- @copyright = FeedTools.unescape_entities(
826
- copyright_node.inner_xml)
827
- else
828
- @copyright = copyright_node.inner_xml
829
- repair_entities = true
830
- end
831
-
832
- unless @copyright.nil?
833
- @copyright = FeedTools.sanitize_html(@copyright, :strip)
834
- @copyright = FeedTools.unescape_entities(@copyright) if repair_entities
835
- @copyright = FeedTools.tidy_html(@copyright)
734
+ @rights = FeedTools::HtmlHelper.process_text_construct(rights_node,
735
+ self.feed_type, self.feed_version)
736
+ if self.feed_type == "atom" ||
737
+ FeedTools.configurations[:always_strip_wrapper_elements]
738
+ @rights = FeedTools::HtmlHelper.strip_wrapper_element(@rights)
836
739
  end
837
-
838
- @copyright = @copyright.strip unless @copyright.nil?
839
- @copyright = nil if @copyright.blank?
840
740
  end
841
- return @copyright
741
+ return @rights
842
742
  end
843
743
 
844
- # Sets the feed item's copyright information
845
- def copyright=(new_copyright)
846
- @copyright = new_copyright
744
+ # Sets the feed item's rights information
745
+ def rights=(new_rights)
746
+ @rights = new_rights
747
+ end
748
+
749
+ def license #:nodoc:
750
+ raise "Not implemented yet."
751
+ end
752
+
753
+ def license=(new_license) #:nodoc:
754
+ raise "Not implemented yet."
847
755
  end
848
756
 
849
757
  # Returns all feed item enclosures
@@ -853,25 +761,32 @@ module FeedTools
853
761
 
854
762
  # First, load up all the different possible sources of enclosures
855
763
  rss_enclosures =
856
- try_xpaths_all(self.root_node, ["enclosure"])
764
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["enclosure"])
857
765
  atom_enclosures =
858
- try_xpaths_all(self.root_node, [
766
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node, [
859
767
  "atom10:link[@rel='enclosure']",
860
768
  "atom03:link[@rel='enclosure']",
861
769
  "atom:link[@rel='enclosure']",
862
770
  "link[@rel='enclosure']"
863
771
  ])
864
772
  media_content_enclosures =
865
- try_xpaths_all(self.root_node, ["media:content"])
773
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node,
774
+ ["media:content"])
866
775
  media_group_enclosures =
867
- try_xpaths_all(self.root_node, ["media:group"])
776
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["media:group"])
777
+
778
+ # TODO: Implement this
779
+ bittorrent_enclosures =
780
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node,
781
+ ["bitTorrent:torrent"])
782
+
868
783
 
869
784
  # Parse RSS-type enclosures. Thanks to a few buggy enclosures
870
785
  # implementations, sometimes these also manage to show up in atom
871
786
  # files.
872
787
  for enclosure_node in rss_enclosures
873
- enclosure = Enclosure.new
874
- enclosure.url = FeedTools.unescape_entities(
788
+ enclosure = FeedTools::Enclosure.new
789
+ enclosure.url = FeedTools::HtmlHelper.unescape_entities(
875
790
  enclosure_node.attributes["url"].to_s)
876
791
  enclosure.type = enclosure_node.attributes["type"].to_s
877
792
  enclosure.file_size = enclosure_node.attributes["length"].to_i
@@ -883,7 +798,7 @@ module FeedTools
883
798
  # Parse atom-type enclosures. If there are repeats of the same
884
799
  # enclosure object, we merge the two together.
885
800
  for enclosure_node in atom_enclosures
886
- enclosure_url = FeedTools.unescape_entities(
801
+ enclosure_url = FeedTools::HtmlHelper.unescape_entities(
887
802
  enclosure_node.attributes["href"].to_s)
888
803
  enclosure = nil
889
804
  new_enclosure = false
@@ -895,7 +810,7 @@ module FeedTools
895
810
  end
896
811
  if enclosure.nil?
897
812
  new_enclosure = true
898
- enclosure = Enclosure.new
813
+ enclosure = FeedTools::Enclosure.new
899
814
  end
900
815
  enclosure.url = enclosure_url
901
816
  enclosure.type = enclosure_node.attributes["type"].to_s
@@ -914,7 +829,7 @@ module FeedTools
914
829
  parse_media_content = lambda do |media_content_nodes|
915
830
  affected_enclosures = []
916
831
  for enclosure_node in media_content_nodes
917
- enclosure_url = FeedTools.unescape_entities(
832
+ enclosure_url = FeedTools::HtmlHelper.unescape_entities(
918
833
  enclosure_node.attributes["url"].to_s)
919
834
  enclosure = nil
920
835
  new_enclosure = false
@@ -926,7 +841,7 @@ module FeedTools
926
841
  end
927
842
  if enclosure.nil?
928
843
  new_enclosure = true
929
- enclosure = Enclosure.new
844
+ enclosure = FeedTools::Enclosure.new
930
845
  end
931
846
  enclosure.url = enclosure_url
932
847
  enclosure.type = enclosure_node.attributes["type"].to_s
@@ -940,29 +855,29 @@ module FeedTools
940
855
  enclosure_node.attributes["expression"].to_s
941
856
  enclosure.is_default =
942
857
  (enclosure_node.attributes["isDefault"].to_s.downcase == "true")
943
- enclosure_thumbnail_url = try_xpaths(enclosure_node,
858
+ enclosure_thumbnail_url = FeedTools::XmlHelper.try_xpaths(enclosure_node,
944
859
  ["media:thumbnail/@url"], :select_result_value => true)
945
860
  if !enclosure_thumbnail_url.blank?
946
- enclosure.thumbnail = EnclosureThumbnail.new(
947
- FeedTools.unescape_entities(enclosure_thumbnail_url),
948
- FeedTools.unescape_entities(
949
- try_xpaths(enclosure_node, ["media:thumbnail/@height"],
861
+ enclosure.thumbnail = FeedTools::EnclosureThumbnail.new(
862
+ FeedTools::HtmlHelper.unescape_entities(enclosure_thumbnail_url),
863
+ FeedTools::HtmlHelper.unescape_entities(
864
+ FeedTools::XmlHelper.try_xpaths(enclosure_node, ["media:thumbnail/@height"],
950
865
  :select_result_value => true)),
951
- FeedTools.unescape_entities(
952
- try_xpaths(enclosure_node, ["media:thumbnail/@width"],
866
+ FeedTools::HtmlHelper.unescape_entities(
867
+ FeedTools::XmlHelper.try_xpaths(enclosure_node, ["media:thumbnail/@width"],
953
868
  :select_result_value => true))
954
869
  )
955
870
  end
956
871
  enclosure.categories = []
957
- for category in try_xpaths_all(enclosure_node, ["media:category"])
958
- enclosure.categories << FeedTools::Feed::Category.new
872
+ for category in FeedTools::XmlHelper.try_xpaths_all(enclosure_node, ["media:category"])
873
+ enclosure.categories << FeedTools::Category.new
959
874
  enclosure.categories.last.term =
960
- FeedTools.unescape_entities(category.inner_xml)
875
+ FeedTools::HtmlHelper.unescape_entities(category.inner_xml)
961
876
  enclosure.categories.last.scheme =
962
- FeedTools.unescape_entities(
877
+ FeedTools::HtmlHelper.unescape_entities(
963
878
  category.attributes["scheme"].to_s)
964
879
  enclosure.categories.last.label =
965
- FeedTools.unescape_entities(
880
+ FeedTools::HtmlHelper.unescape_entities(
966
881
  category.attributes["label"].to_s)
967
882
  if enclosure.categories.last.scheme.blank?
968
883
  enclosure.categories.last.scheme = nil
@@ -971,33 +886,33 @@ module FeedTools
971
886
  enclosure.categories.last.label = nil
972
887
  end
973
888
  end
974
- enclosure_media_hash = try_xpaths(enclosure_node,
889
+ enclosure_media_hash = FeedTools::XmlHelper.try_xpaths(enclosure_node,
975
890
  ["media:hash/text()"], :select_result_value => true)
976
891
  if !enclosure_media_hash.nil?
977
- enclosure.hash = EnclosureHash.new(
978
- FeedTools.sanitize_html(FeedTools.unescape_entities(
892
+ enclosure.hash = FeedTools::EnclosureHash.new(
893
+ FeedTools::HtmlHelper.sanitize_html(FeedTools::HtmlHelper.unescape_entities(
979
894
  enclosure_media_hash), :strip),
980
895
  "md5"
981
896
  )
982
897
  end
983
- enclosure_media_player_url = try_xpaths(enclosure_node,
898
+ enclosure_media_player_url = FeedTools::XmlHelper.try_xpaths(enclosure_node,
984
899
  ["media:player/@url"], :select_result_value => true)
985
900
  if !enclosure_media_player_url.blank?
986
- enclosure.player = EnclosurePlayer.new(
987
- FeedTools.unescape_entities(enclosure_media_player_url),
988
- FeedTools.unescape_entities(
989
- try_xpaths(enclosure_node,
901
+ enclosure.player = FeedTools::EnclosurePlayer.new(
902
+ FeedTools::HtmlHelper.unescape_entities(enclosure_media_player_url),
903
+ FeedTools::HtmlHelper.unescape_entities(
904
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
990
905
  ["media:player/@height"], :select_result_value => true)),
991
- FeedTools.unescape_entities(
992
- try_xpaths(enclosure_node,
906
+ FeedTools::HtmlHelper.unescape_entities(
907
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
993
908
  ["media:player/@width"], :select_result_value => true))
994
909
  )
995
910
  end
996
911
  enclosure.credits = []
997
- for credit in try_xpaths_all(enclosure_node, ["media:credit"])
998
- enclosure.credits << EnclosureCredit.new(
999
- FeedTools.unescape_entities(credit.inner_xml.to_s.strip),
1000
- FeedTools.unescape_entities(
912
+ for credit in FeedTools::XmlHelper.try_xpaths_all(enclosure_node, ["media:credit"])
913
+ enclosure.credits << FeedTools::EnclosureCredit.new(
914
+ FeedTools::HtmlHelper.unescape_entities(credit.inner_xml.to_s.strip),
915
+ FeedTools::HtmlHelper.unescape_entities(
1001
916
  credit.attributes["role"].to_s.downcase)
1002
917
  )
1003
918
  if enclosure.credits.last.name.blank?
@@ -1007,12 +922,12 @@ module FeedTools
1007
922
  enclosure.credits.last.role = nil
1008
923
  end
1009
924
  end
1010
- enclosure.explicit = (try_xpaths(enclosure_node,
925
+ enclosure.explicit = (FeedTools::XmlHelper.try_xpaths(enclosure_node,
1011
926
  ["media:adult/text()"]).to_s.downcase == "true")
1012
927
  enclosure_media_text =
1013
- try_xpaths(enclosure_node, ["media:text/text()"])
928
+ FeedTools::XmlHelper.try_xpaths(enclosure_node, ["media:text/text()"])
1014
929
  if !enclosure_media_text.blank?
1015
- enclosure.text = FeedTools.unescape_entities(
930
+ enclosure.text = FeedTools::HtmlHelper.unescape_entities(
1016
931
  enclosure_media_text)
1017
932
  end
1018
933
  affected_enclosures << enclosure
@@ -1031,7 +946,7 @@ module FeedTools
1031
946
  # Parse the group objects.
1032
947
  for media_group in media_group_enclosures
1033
948
  group_media_content_enclosures =
1034
- try_xpaths_all(media_group, ["media:content"])
949
+ FeedTools::XmlHelper.try_xpaths_all(media_group, ["media:content"])
1035
950
 
1036
951
  # Parse the content objects within the group objects.
1037
952
  affected_enclosures =
@@ -1040,31 +955,31 @@ module FeedTools
1040
955
  # Now make sure that content objects inherit certain properties from
1041
956
  # the group objects.
1042
957
  for enclosure in affected_enclosures
1043
- media_group_thumbnail = try_xpaths(media_group,
958
+ media_group_thumbnail = FeedTools::XmlHelper.try_xpaths(media_group,
1044
959
  ["media:thumbnail/@url"], :select_result_value => true)
1045
960
  if enclosure.thumbnail.nil? && !media_group_thumbnail.blank?
1046
- enclosure.thumbnail = EnclosureThumbnail.new(
1047
- FeedTools.unescape_entities(
961
+ enclosure.thumbnail = FeedTools::EnclosureThumbnail.new(
962
+ FeedTools::HtmlHelper.unescape_entities(
1048
963
  media_group_thumbnail),
1049
- FeedTools.unescape_entities(
1050
- try_xpaths(media_group, ["media:thumbnail/@height"],
964
+ FeedTools::HtmlHelper.unescape_entities(
965
+ FeedTools::XmlHelper.try_xpaths(media_group, ["media:thumbnail/@height"],
1051
966
  :select_result_value => true)),
1052
- FeedTools.unescape_entities(
1053
- try_xpaths(media_group, ["media:thumbnail/@width"],
967
+ FeedTools::HtmlHelper.unescape_entities(
968
+ FeedTools::XmlHelper.try_xpaths(media_group, ["media:thumbnail/@width"],
1054
969
  :select_result_value => true))
1055
970
  )
1056
971
  end
1057
972
  if (enclosure.categories.blank?)
1058
973
  enclosure.categories = []
1059
- for category in try_xpaths_all(media_group, ["media:category"])
1060
- enclosure.categories << FeedTools::Feed::Category.new
974
+ for category in FeedTools::XmlHelper.try_xpaths_all(media_group, ["media:category"])
975
+ enclosure.categories << FeedTools::Category.new
1061
976
  enclosure.categories.last.term =
1062
- FeedTools.unescape_entities(category.inner_xml)
977
+ FeedTools::HtmlHelper.unescape_entities(category.inner_xml)
1063
978
  enclosure.categories.last.scheme =
1064
- FeedTools.unescape_entities(
979
+ FeedTools::HtmlHelper.unescape_entities(
1065
980
  category.attributes["scheme"].to_s)
1066
981
  enclosure.categories.last.label =
1067
- FeedTools.unescape_entities(
982
+ FeedTools::HtmlHelper.unescape_entities(
1068
983
  category.attributes["label"].to_s)
1069
984
  if enclosure.categories.last.scheme.blank?
1070
985
  enclosure.categories.last.scheme = nil
@@ -1074,34 +989,34 @@ module FeedTools
1074
989
  end
1075
990
  end
1076
991
  end
1077
- enclosure_media_group_hash = try_xpaths(enclosure_node,
992
+ enclosure_media_group_hash = FeedTools::XmlHelper.try_xpaths(enclosure_node,
1078
993
  ["media:hash/text()"], :select_result_value => true)
1079
994
  if enclosure.hash.nil? && !enclosure_media_group_hash.blank?
1080
- enclosure.hash = EnclosureHash.new(
1081
- FeedTools.sanitize_html(FeedTools.unescape_entities(
995
+ enclosure.hash = FeedTools::EnclosureHash.new(
996
+ FeedTools::HtmlHelper.sanitize_html(FeedTools::HtmlHelper.unescape_entities(
1082
997
  enclosure_media_group_hash), :strip),
1083
998
  "md5"
1084
999
  )
1085
1000
  end
1086
- enclosure_media_group_url = try_xpaths(media_group,
1001
+ enclosure_media_group_url = FeedTools::XmlHelper.try_xpaths(media_group,
1087
1002
  "media:player/@url", :select_result_value => true)
1088
1003
  if enclosure.player.nil? && !enclosure_media_group_url.blank?
1089
- enclosure.player = EnclosurePlayer.new(
1090
- FeedTools.unescape_entities(enclosure_media_group_url),
1091
- FeedTools.unescape_entities(
1092
- try_xpaths(media_group, ["media:player/@height"],
1004
+ enclosure.player = FeedTools::EnclosurePlayer.new(
1005
+ FeedTools::HtmlHelper.unescape_entities(enclosure_media_group_url),
1006
+ FeedTools::HtmlHelper.unescape_entities(
1007
+ FeedTools::XmlHelper.try_xpaths(media_group, ["media:player/@height"],
1093
1008
  :select_result_value => true)),
1094
- FeedTools.unescape_entities(
1095
- try_xpaths(media_group, ["media:player/@width"],
1009
+ FeedTools::HtmlHelper.unescape_entities(
1010
+ FeedTools::XmlHelper.try_xpaths(media_group, ["media:player/@width"],
1096
1011
  :select_result_value => true))
1097
1012
  )
1098
1013
  end
1099
1014
  if enclosure.credits.nil? || enclosure.credits.size == 0
1100
1015
  enclosure.credits = []
1101
- for credit in try_xpaths_all(media_group, ["media:credit"])
1102
- enclosure.credits << EnclosureCredit.new(
1103
- FeedTools.unescape_entities(credit.inner_xml),
1104
- FeedTools.unescape_entities(
1016
+ for credit in FeedTools::XmlHelper.try_xpaths_all(media_group, ["media:credit"])
1017
+ enclosure.credits << FeedTools::EnclosureCredit.new(
1018
+ FeedTools::HtmlHelper.unescape_entities(credit.inner_xml),
1019
+ FeedTools::HtmlHelper.unescape_entities(
1105
1020
  credit.attributes["role"].to_s.downcase)
1106
1021
  )
1107
1022
  if enclosure.credits.last.role.blank?
@@ -1110,16 +1025,16 @@ module FeedTools
1110
1025
  end
1111
1026
  end
1112
1027
  if enclosure.explicit?.nil?
1113
- enclosure.explicit = ((try_xpaths(media_group, [
1028
+ enclosure.explicit = ((FeedTools::XmlHelper.try_xpaths(media_group, [
1114
1029
  "media:adult/text()"
1115
1030
  ], :select_result_value => true).downcase == "true") ?
1116
1031
  true : false)
1117
1032
  end
1118
- enclosure_media_group_text = try_xpaths(media_group,
1033
+ enclosure_media_group_text = FeedTools::XmlHelper.try_xpaths(media_group,
1119
1034
  ["media:text/text()"], :select_result_value => true)
1120
1035
  if enclosure.text.nil? && !enclosure_media_group_text.blank?
1121
- enclosure.text = FeedTools.sanitize_html(
1122
- FeedTools.unescape_entities(
1036
+ enclosure.text = FeedTools::HtmlHelper.sanitize_html(
1037
+ FeedTools::HtmlHelper.unescape_entities(
1123
1038
  enclosure_media_group_text), :strip)
1124
1039
  end
1125
1040
  end
@@ -1137,27 +1052,27 @@ module FeedTools
1137
1052
 
1138
1053
  # Add all the itunes categories
1139
1054
  itunes_categories =
1140
- try_xpaths_all(self.root_node, ["itunes:category"])
1055
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["itunes:category"])
1141
1056
  for itunes_category in itunes_categories
1142
1057
  genre = "Podcasts"
1143
1058
  category = itunes_category.attributes["text"].to_s
1144
1059
  subcategory =
1145
- try_xpaths(itunes_category, ["itunes:category/@text"],
1060
+ FeedTools::XmlHelper.try_xpaths(itunes_category, ["itunes:category/@text"],
1146
1061
  :select_result_value => true)
1147
1062
  category_path = genre
1148
- if category != ""
1063
+ if !category.blank?
1149
1064
  category_path << "/" + category
1150
1065
  end
1151
- if subcategory != ""
1066
+ if !subcategory.blank?
1152
1067
  category_path << "/" + subcategory
1153
1068
  end
1154
1069
  for enclosure in @enclosures
1155
1070
  if enclosure.categories.nil?
1156
1071
  enclosure.categories = []
1157
1072
  end
1158
- enclosure.categories << FeedTools::Feed::Category.new
1073
+ enclosure.categories << FeedTools::Category.new
1159
1074
  enclosure.categories.last.term =
1160
- FeedTools.unescape_entities(category_path)
1075
+ FeedTools::HtmlHelper.unescape_entities(category_path)
1161
1076
  enclosure.categories.last.scheme =
1162
1077
  "http://www.apple.com/itunes/store/"
1163
1078
  enclosure.categories.last.label =
@@ -1254,8 +1169,8 @@ module FeedTools
1254
1169
  # Returns the feed item author
1255
1170
  def author
1256
1171
  if @author.nil?
1257
- @author = FeedTools::Feed::Author.new
1258
- author_node = try_xpaths(self.root_node, [
1172
+ @author = FeedTools::Author.new
1173
+ author_node = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1259
1174
  "atom10:author",
1260
1175
  "atom03:author",
1261
1176
  "atom:author",
@@ -1266,9 +1181,9 @@ module FeedTools
1266
1181
  "creator"
1267
1182
  ])
1268
1183
  unless author_node.nil?
1269
- @author.raw = FeedTools.unescape_entities(
1270
- XPath.first(author_node, "text()").to_s).strip
1271
- @author.raw = nil if @author.raw.blank?
1184
+ @author.raw = FeedTools::XmlHelper.try_xpaths(
1185
+ author_node, ["text()"], :select_result_value => true)
1186
+ @author.raw = FeedTools::HtmlHelper.unescape_entities(@author.raw)
1272
1187
  unless @author.raw.nil?
1273
1188
  raw_scan = @author.raw.scan(
1274
1189
  /(.*)\((\b[A-Z0-9._%-\+]+@[A-Z0-9._%-]+\.[A-Z]{2,4}\b)\)/i)
@@ -1302,8 +1217,8 @@ module FeedTools
1302
1217
  end
1303
1218
  end
1304
1219
  if @author.name.blank?
1305
- @author.name = FeedTools.unescape_entities(
1306
- try_xpaths(author_node, [
1220
+ @author.name = FeedTools::HtmlHelper.unescape_entities(
1221
+ FeedTools::XmlHelper.try_xpaths(author_node, [
1307
1222
  "atom10:name/text()",
1308
1223
  "atom03:name/text()",
1309
1224
  "atom:name/text()",
@@ -1313,8 +1228,8 @@ module FeedTools
1313
1228
  )
1314
1229
  end
1315
1230
  if @author.email.blank?
1316
- @author.email = FeedTools.unescape_entities(
1317
- try_xpaths(author_node, [
1231
+ @author.email = FeedTools::HtmlHelper.unescape_entities(
1232
+ FeedTools::XmlHelper.try_xpaths(author_node, [
1318
1233
  "atom10:email/text()",
1319
1234
  "atom03:email/text()",
1320
1235
  "atom:email/text()",
@@ -1324,8 +1239,8 @@ module FeedTools
1324
1239
  )
1325
1240
  end
1326
1241
  if @author.url.blank?
1327
- @author.url = FeedTools.unescape_entities(
1328
- try_xpaths(author_node, [
1242
+ @author.url = FeedTools::HtmlHelper.unescape_entities(
1243
+ FeedTools::XmlHelper.try_xpaths(author_node, [
1329
1244
  "atom10:url/text()",
1330
1245
  "atom03:url/text()",
1331
1246
  "atom:url/text()",
@@ -1344,6 +1259,16 @@ module FeedTools
1344
1259
  @author.raw = nil if @author.raw.blank?
1345
1260
  @author.email = nil if @author.email.blank?
1346
1261
  @author.url = nil if @author.url.blank?
1262
+ if @author.url != nil
1263
+ begin
1264
+ if !(@author.url =~ /^file:/) &&
1265
+ !FeedTools::UriHelper.is_uri?(@author.url)
1266
+ @author.url = FeedTools::UriHelper.resolve_relative_uri(
1267
+ @author.url, [author_node.base_uri, self.base_uri])
1268
+ end
1269
+ rescue
1270
+ end
1271
+ end
1347
1272
  end
1348
1273
  # Fallback on the itunes module if we didn't find an author name
1349
1274
  begin
@@ -1366,7 +1291,7 @@ module FeedTools
1366
1291
  # We're not looking at an author object, this is probably a string,
1367
1292
  # default to setting the author's name.
1368
1293
  if @author.nil?
1369
- @author = FeedTools::Feed::Author.new
1294
+ @author = FeedTools::Author.new
1370
1295
  end
1371
1296
  @author.name = new_author
1372
1297
  end
@@ -1375,11 +1300,11 @@ module FeedTools
1375
1300
  # Returns the feed publisher
1376
1301
  def publisher
1377
1302
  if @publisher.nil?
1378
- @publisher = FeedTools::Feed::Author.new
1303
+ @publisher = FeedTools::Author.new
1379
1304
 
1380
1305
  # Set the author name
1381
- @publisher.raw = FeedTools.unescape_entities(
1382
- try_xpaths(self.root_node, [
1306
+ @publisher.raw = FeedTools::HtmlHelper.unescape_entities(
1307
+ FeedTools::XmlHelper.try_xpaths(self.root_node, [
1383
1308
  "dc:publisher/text()",
1384
1309
  "webMaster/text()"
1385
1310
  ], :select_result_value => true))
@@ -1420,6 +1345,20 @@ module FeedTools
1420
1345
  @publisher.raw = nil if @publisher.raw.blank?
1421
1346
  @publisher.email = nil if @publisher.email.blank?
1422
1347
  @publisher.url = nil if @publisher.url.blank?
1348
+ if @publisher.url != nil
1349
+ begin
1350
+ if !(@publisher.url =~ /^file:/) &&
1351
+ !FeedTools::UriHelper.is_uri?(@publisher.url)
1352
+ root_base_uri = nil
1353
+ unless self.root_node.nil?
1354
+ root_base_uri = self.root_node.base_uri
1355
+ end
1356
+ @publisher.url = FeedTools::UriHelper.resolve_relative_uri(
1357
+ @publisher.url, [root_base_uri, self.base_uri])
1358
+ end
1359
+ rescue
1360
+ end
1361
+ end
1423
1362
  end
1424
1363
  return @publisher
1425
1364
  end
@@ -1435,7 +1374,7 @@ module FeedTools
1435
1374
  # We're not looking at an Author object, this is probably a string,
1436
1375
  # default to setting the publisher's name.
1437
1376
  if @publisher.nil?
1438
- @publisher = FeedTools::Feed::Author.new
1377
+ @publisher = FeedTools::Author.new
1439
1378
  end
1440
1379
  @publisher.name = new_publisher
1441
1380
  end
@@ -1447,8 +1386,8 @@ module FeedTools
1447
1386
  # elements. They're actually amazingly common. People don't read specs.
1448
1387
  def itunes_author
1449
1388
  if @itunes_author.nil?
1450
- @itunes_author = FeedTools.unescape_entities(
1451
- try_xpaths(self.root_node,
1389
+ @itunes_author = FeedTools::HtmlHelper.unescape_entities(
1390
+ FeedTools::XmlHelper.try_xpaths(self.root_node,
1452
1391
  ["itunes:author/text()"], :select_result_value => true))
1453
1392
  @itunes_author = feed.itunes_author if @itunes_author.blank?
1454
1393
  end
@@ -1463,8 +1402,8 @@ module FeedTools
1463
1402
  # Returns the number of seconds that the associated media runs for
1464
1403
  def itunes_duration
1465
1404
  if @itunes_duration.nil?
1466
- raw_duration = FeedTools.unescape_entities(
1467
- try_xpaths(self.root_node,
1405
+ raw_duration = FeedTools::HtmlHelper.unescape_entities(
1406
+ FeedTools::XmlHelper.try_xpaths(self.root_node,
1468
1407
  ["itunes:duration/text()"], :select_result_value => true))
1469
1408
  if !raw_duration.blank?
1470
1409
  hms = raw_duration.split(":").map { |x| x.to_i }
@@ -1487,11 +1426,11 @@ module FeedTools
1487
1426
 
1488
1427
  # Returns the feed item time
1489
1428
  def time(options = {})
1490
- validate_options([ :estimate_timestamp ],
1429
+ FeedTools::GenericHelper.validate_options([ :estimate_timestamp ],
1491
1430
  options.keys)
1492
1431
  options = { :estimate_timestamp => true }.merge(options)
1493
1432
  if @time.nil?
1494
- time_string = try_xpaths(self.root_node, [
1433
+ time_string = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1495
1434
  "atom10:updated/text()",
1496
1435
  "atom03:updated/text()",
1497
1436
  "atom:updated/text()",
@@ -1501,6 +1440,7 @@ module FeedTools
1501
1440
  "atom:modified/text()",
1502
1441
  "modified/text()",
1503
1442
  "time/text()",
1443
+ "lastBuildDate/text()",
1504
1444
  "atom10:issued/text()",
1505
1445
  "atom03:issued/text()",
1506
1446
  "atom:issued/text()",
@@ -1509,8 +1449,8 @@ module FeedTools
1509
1449
  "atom03:published/text()",
1510
1450
  "atom:published/text()",
1511
1451
  "published/text()",
1512
- "pubDate/text()",
1513
1452
  "dc:date/text()",
1453
+ "pubDate/text()",
1514
1454
  "date/text()"
1515
1455
  ], :select_result_value => true)
1516
1456
  begin
@@ -1603,7 +1543,7 @@ module FeedTools
1603
1543
  # Returns the feed item updated time
1604
1544
  def updated
1605
1545
  if @updated.nil?
1606
- updated_string = try_xpaths(self.root_node, [
1546
+ updated_string = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1607
1547
  "atom10:updated/text()",
1608
1548
  "atom03:updated/text()",
1609
1549
  "atom:updated/text()",
@@ -1611,7 +1551,8 @@ module FeedTools
1611
1551
  "atom10:modified/text()",
1612
1552
  "atom03:modified/text()",
1613
1553
  "atom:modified/text()",
1614
- "modified/text()"
1554
+ "modified/text()",
1555
+ "lastBuildDate/text()"
1615
1556
  ], :select_result_value => true)
1616
1557
  if !updated_string.blank?
1617
1558
  @updated = Time.parse(updated_string).gmtime rescue nil
@@ -1630,7 +1571,7 @@ module FeedTools
1630
1571
  # Returns the feed item published time
1631
1572
  def published
1632
1573
  if @published.nil?
1633
- published_string = try_xpaths(self.root_node, [
1574
+ published_string = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1634
1575
  "atom10:issued/text()",
1635
1576
  "atom03:issued/text()",
1636
1577
  "atom:issued/text()",
@@ -1639,17 +1580,17 @@ module FeedTools
1639
1580
  "atom03:published/text()",
1640
1581
  "atom:published/text()",
1641
1582
  "published/text()",
1642
- "pubDate/text()",
1643
1583
  "dc:date/text()",
1584
+ "pubDate/text()",
1644
1585
  "date/text()"
1645
1586
  ], :select_result_value => true)
1646
1587
  if !published_string.blank?
1647
- @issued = Time.parse(published_string).gmtime rescue nil
1588
+ @published = Time.parse(published_string).gmtime rescue nil
1648
1589
  else
1649
- @issued = nil
1590
+ @published = nil
1650
1591
  end
1651
1592
  end
1652
- return @issued
1593
+ return @published
1653
1594
  end
1654
1595
 
1655
1596
  # Sets the feed item published time
@@ -1660,10 +1601,22 @@ module FeedTools
1660
1601
  # Returns the url for posting comments
1661
1602
  def comments
1662
1603
  if @comments.nil?
1663
- @comments = try_xpaths(self.root_node, ["comments/text()"],
1604
+ @comments = FeedTools::XmlHelper.try_xpaths(self.root_node, ["comments/text()"],
1664
1605
  :select_result_value => true)
1606
+ begin
1607
+ if !(@comments =~ /^file:/) &&
1608
+ !FeedTools::UriHelper.is_uri?(@comments)
1609
+ root_base_uri = nil
1610
+ unless self.root_node.nil?
1611
+ root_base_uri = self.root_node.base_uri
1612
+ end
1613
+ @comments = FeedTools::UriHelper.resolve_relative_uri(
1614
+ @comments, [root_base_uri, self.base_uri])
1615
+ end
1616
+ rescue
1617
+ end
1665
1618
  if FeedTools.configurations[:url_normalization_enabled]
1666
- @comments = FeedTools.normalize_url(@comments)
1619
+ @comments = FeedTools::UriHelper.normalize_url(@comments)
1667
1620
  end
1668
1621
  end
1669
1622
  return @comments
@@ -1677,10 +1630,12 @@ module FeedTools
1677
1630
  # The source that this post was based on
1678
1631
  def source
1679
1632
  if @source.nil?
1680
- @source = FeedTools::Feed::Link.new
1681
- @source.url = try_xpaths(self.root_node, ["source/@url"],
1633
+ @source = FeedTools::Link.new
1634
+ @source.href = FeedTools::XmlHelper.try_xpaths(
1635
+ self.root_node, ["source/@url"],
1682
1636
  :select_result_value => true)
1683
- @source.value = try_xpaths(self.root_node, ["source/text()"],
1637
+ @source.title = FeedTools::XmlHelper.try_xpaths(
1638
+ self.root_node, ["source/text()"],
1684
1639
  :select_result_value => true)
1685
1640
  end
1686
1641
  return @source
@@ -1697,7 +1652,7 @@ module FeedTools
1697
1652
  end
1698
1653
  if @tags.nil? || @tags.size == 0
1699
1654
  @tags = []
1700
- tag_list = try_xpaths_all(self.root_node,
1655
+ tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node,
1701
1656
  ["dc:subject/rdf:Bag/rdf:li/text()"],
1702
1657
  :select_result_value => true)
1703
1658
  if tag_list != nil && tag_list.size > 0
@@ -1709,12 +1664,12 @@ module FeedTools
1709
1664
  if @tags.nil? || @tags.size == 0
1710
1665
  # messy effort to find ourselves some tags, mainly for del.icio.us
1711
1666
  @tags = []
1712
- rdf_bag = try_xpaths_all(self.root_node,
1667
+ rdf_bag = FeedTools::XmlHelper.try_xpaths_all(self.root_node,
1713
1668
  ["taxo:topics/rdf:Bag/rdf:li"])
1714
1669
  if rdf_bag != nil && rdf_bag.size > 0
1715
1670
  for tag_node in rdf_bag
1716
1671
  begin
1717
- tag_url = try_xpaths(tag_node, ["@resource"],
1672
+ tag_url = FeedTools::XmlHelper.try_xpaths(tag_node, ["@resource"],
1718
1673
  :select_result_value => true)
1719
1674
  tag_match = tag_url.scan(/\/(tag|tags)\/(\w+)$/)
1720
1675
  if tag_match.size > 0
@@ -1727,7 +1682,7 @@ module FeedTools
1727
1682
  end
1728
1683
  if @tags.nil? || @tags.size == 0
1729
1684
  @tags = []
1730
- tag_list = try_xpaths_all(self.root_node, ["category/text()"],
1685
+ tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["category/text()"],
1731
1686
  :select_result_value => true)
1732
1687
  for tag in tag_list
1733
1688
  @tags << tag.to_s.downcase.strip
@@ -1735,7 +1690,7 @@ module FeedTools
1735
1690
  end
1736
1691
  if @tags.nil? || @tags.size == 0
1737
1692
  @tags = []
1738
- tag_list = try_xpaths_all(self.root_node, ["dc:subject/text()"],
1693
+ tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["dc:subject/text()"],
1739
1694
  :select_result_value => true)
1740
1695
  for tag in tag_list
1741
1696
  @tags << tag.to_s.downcase.strip
@@ -1743,7 +1698,7 @@ module FeedTools
1743
1698
  end
1744
1699
  if @tags.blank?
1745
1700
  begin
1746
- itunes_keywords_string = try_xpaths(self.root_node, [
1701
+ itunes_keywords_string = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1747
1702
  "itunes:keywords/text()"
1748
1703
  ], :select_result_value => true)
1749
1704
  unless itunes_keywords_string.blank?
@@ -1779,7 +1734,7 @@ module FeedTools
1779
1734
  # isn't explicitly marked as explicit.
1780
1735
  def explicit?
1781
1736
  if @explicit.nil?
1782
- explicit_string = try_xpaths(self.root_node, [
1737
+ explicit_string = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1783
1738
  "media:adult/text()",
1784
1739
  "itunes:explicit/text()"
1785
1740
  ], :select_result_value => true)
@@ -1819,32 +1774,39 @@ module FeedTools
1819
1774
  raise "Cannot generate an rdf-based feed item with a nil link field."
1820
1775
  end
1821
1776
  return xml_builder.item("rdf:about" =>
1822
- FeedTools.escape_entities(link)) do
1823
- unless title.nil? || title == ""
1824
- xml_builder.title(title)
1777
+ FeedTools::HtmlHelper.escape_entities(link)) do
1778
+ unless self.title.blank?
1779
+ xml_builder.title(FeedTools::HtmlHelper.strip_html_tags(self.title))
1825
1780
  else
1826
1781
  xml_builder.title
1827
1782
  end
1828
- unless link.nil? || link == ""
1829
- xml_builder.link(link)
1783
+ unless self.link.blank?
1784
+ xml_builder.link(self.link)
1830
1785
  else
1831
1786
  xml_builder.link
1832
1787
  end
1833
- unless description.nil? || description == ""
1834
- xml_builder.description(description)
1788
+ unless self.author.nil? || self.author.name.nil?
1789
+ xml_builder.tag!("dc:creator", self.author.name)
1790
+ end
1791
+ unless self.summary.blank?
1792
+ xml_builder.description(self.summary)
1835
1793
  else
1836
1794
  xml_builder.description
1837
1795
  end
1796
+ unless self.content.blank?
1797
+ xml_builder.tag!("content:encoded") do
1798
+ xml_builder.cdata!(self.content)
1799
+ end
1800
+ end
1838
1801
  unless time.nil?
1839
1802
  xml_builder.tag!("dc:date", time.iso8601)
1840
1803
  end
1804
+ unless self.rights.blank?
1805
+ xml_builder.tag!("dc:rights", self.rights)
1806
+ end
1841
1807
  unless tags.nil? || tags.size == 0
1842
- xml_builder.tag!("taxo:topics") do
1843
- xml_builder.tag!("rdf:Bag") do
1844
- for tag in tags
1845
- xml_builder.tag!("rdf:li", tag)
1846
- end
1847
- end
1808
+ for tag in tags
1809
+ xml_builder.tag!("dc:subject", tag)
1848
1810
  end
1849
1811
  if self.feed.podcast?
1850
1812
  xml_builder.tag!("itunes:keywords", tags.join(", "))
@@ -1856,19 +1818,32 @@ module FeedTools
1856
1818
  # normal rss format
1857
1819
  return xml_builder.item do
1858
1820
  unless self.title.blank?
1859
- xml_builder.title(self.title)
1821
+ xml_builder.title(FeedTools::HtmlHelper.strip_html_tags(self.title))
1860
1822
  end
1861
1823
  unless self.link.blank?
1862
1824
  xml_builder.link(link)
1863
1825
  end
1864
- unless self.description.blank?
1865
- xml_builder.description(self.description)
1826
+ unless self.author.nil? || self.author.name.nil?
1827
+ xml_builder.tag!("dc:creator", self.author.name)
1828
+ end
1829
+ unless self.summary.blank?
1830
+ xml_builder.description(self.summary)
1866
1831
  end
1867
- unless self.time.nil?
1832
+ unless self.content.blank?
1833
+ xml_builder.tag!("content:encoded") do
1834
+ xml_builder.cdata!(self.content)
1835
+ end
1836
+ end
1837
+ if !self.published.nil?
1838
+ xml_builder.pubDate(self.published.rfc822)
1839
+ elsif !self.time.nil?
1868
1840
  xml_builder.pubDate(self.time.rfc822)
1869
1841
  end
1842
+ unless self.copyright.blank?
1843
+ xml_builder.tag!("dc:rights", self.copyright)
1844
+ end
1870
1845
  unless self.guid.blank?
1871
- if FeedTools.is_uri?(self.guid)
1846
+ if FeedTools::UriHelper.is_uri?(self.guid) && (self.guid =~ /^http/)
1872
1847
  xml_builder.guid(self.guid, "isPermaLink" => "true")
1873
1848
  else
1874
1849
  xml_builder.guid(self.guid, "isPermaLink" => "false")
@@ -1879,12 +1854,8 @@ module FeedTools
1879
1854
  end
1880
1855
  end
1881
1856
  unless tags.nil? || tags.size == 0
1882
- xml_builder.tag!("taxo:topics") do
1883
- xml_builder.tag!("rdf:Bag") do
1884
- for tag in tags
1885
- xml_builder.tag!("rdf:li", tag)
1886
- end
1887
- end
1857
+ for tag in tags
1858
+ xml_builder.tag!("category", tag)
1888
1859
  end
1889
1860
  if self.feed.podcast?
1890
1861
  xml_builder.tag!("itunes:keywords", tags.join(", "))
@@ -1911,7 +1882,7 @@ module FeedTools
1911
1882
  end
1912
1883
  rescue
1913
1884
  end
1914
- attribute_hash["url"] = FeedTools.normalize_url(enclosure.url)
1885
+ attribute_hash["url"] = FeedTools::UriHelper.normalize_url(enclosure.url)
1915
1886
  if enclosure.type != nil
1916
1887
  attribute_hash["type"] = enclosure.type
1917
1888
  end
@@ -1936,7 +1907,8 @@ module FeedTools
1936
1907
  return xml_builder.entry("xmlns" =>
1937
1908
  FEED_TOOLS_NAMESPACES['atom10']) do
1938
1909
  unless title.nil? || title == ""
1939
- xml_builder.title(title,
1910
+ xml_builder.title(
1911
+ FeedTools::HtmlHelper.strip_html_tags(self.title),
1940
1912
  "type" => "html")
1941
1913
  end
1942
1914
  xml_builder.author do
@@ -1953,10 +1925,10 @@ module FeedTools
1953
1925
  end
1954
1926
  end
1955
1927
  unless link.nil? || link == ""
1956
- xml_builder.link("href" => FeedTools.escape_entities(self.link),
1957
- "rel" => "alternate",
1958
- "type" => "text/html",
1959
- "title" => FeedTools.escape_entities(title))
1928
+ xml_builder.link(
1929
+ "href" =>
1930
+ FeedTools::HtmlHelper.escape_entities(self.link),
1931
+ "rel" => "alternate")
1960
1932
  end
1961
1933
  if !self.content.blank?
1962
1934
  xml_builder.content(self.content,
@@ -1978,10 +1950,13 @@ module FeedTools
1978
1950
  unless self.published.nil?
1979
1951
  xml_builder.published(self.published.iso8601)
1980
1952
  end
1953
+ unless self.rights.blank?
1954
+ xml_builder.rights(self.rights)
1955
+ end
1981
1956
  if self.id != nil
1982
- unless FeedTools.is_uri? self.id
1957
+ unless FeedTools::UriHelper.is_uri? self.id
1983
1958
  if self.time != nil && self.link != nil
1984
- xml_builder.id(FeedTools.build_tag_uri(self.link, self.time))
1959
+ xml_builder.id(FeedTools::UriHelper.build_tag_uri(self.link, self.time))
1985
1960
  elsif self.link != nil
1986
1961
  xml_builder.id(FeedTools.build_urn_uuid_uri(self.link))
1987
1962
  else
@@ -1992,7 +1967,7 @@ module FeedTools
1992
1967
  xml_builder.id(self.id)
1993
1968
  end
1994
1969
  elsif self.time != nil && self.link != nil
1995
- xml_builder.id(FeedTools.build_tag_uri(self.link, self.time))
1970
+ xml_builder.id(FeedTools::UriHelper.build_tag_uri(self.link, self.time))
1996
1971
  else
1997
1972
  raise "Cannot build feed, missing feed unique id."
1998
1973
  end
@@ -2006,7 +1981,7 @@ module FeedTools
2006
1981
  attribute_hash = {}
2007
1982
  next if enclosure.url.blank?
2008
1983
  attribute_hash["rel"] = "enclosure"
2009
- attribute_hash["href"] = FeedTools.normalize_url(enclosure.url)
1984
+ attribute_hash["href"] = FeedTools::UriHelper.normalize_url(enclosure.url)
2010
1985
  if enclosure.type != nil
2011
1986
  attribute_hash["type"] = enclosure.type
2012
1987
  end
@@ -2023,10 +1998,12 @@ module FeedTools
2023
1998
  end
2024
1999
  end
2025
2000
 
2026
- alias_method :abstract, :content
2027
- alias_method :abstract=, :content=
2028
- alias_method :description, :content
2029
- alias_method :description=, :content=
2001
+ alias_method :abstract, :summary
2002
+ alias_method :abstract=, :summary=
2003
+ alias_method :description, :summary
2004
+ alias_method :description=, :summary=
2005
+ alias_method :copyright, :rights
2006
+ alias_method :copyright=, :rights=
2030
2007
  alias_method :guid, :id
2031
2008
  alias_method :guid=, :id=
2032
2009