feedtools 0.2.22 → 0.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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