feedtools 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -2
- data/lib/feed_tools.rb +489 -62
- data/rakefile +1 -1
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
== FeedTools 0.2.7
|
2
|
+
* added support for Atom 1.0 output
|
3
|
+
* improved support for Atom parsing and handling
|
4
|
+
* added no content string option to keep the feed validator happy
|
5
|
+
* greatly improved handling of timestamps and feed item sorting
|
6
|
+
* added aliases for the Atom 1.0 elements that were renamed
|
7
|
+
* feed merging is now threaded
|
1
8
|
== FeedTools 0.2.6
|
2
|
-
*
|
3
|
-
*
|
9
|
+
* added support for merging feeds
|
10
|
+
* vastly improved handling of feed creation
|
4
11
|
== FeedTools 0.2.5
|
5
12
|
* fixed multiple rows being created in the cache after a 301 redirection
|
6
13
|
* fixed broken table creation for postgresql and sqlite
|
data/lib/feed_tools.rb
CHANGED
@@ -25,7 +25,7 @@ FEED_TOOLS_ENV = ENV['FEED_TOOLS_ENV'] ||
|
|
25
25
|
ENV['RAILS_ENV'] ||
|
26
26
|
'production' # :nodoc:
|
27
27
|
|
28
|
-
FEED_TOOLS_VERSION = "0.2.
|
28
|
+
FEED_TOOLS_VERSION = "0.2.7"
|
29
29
|
|
30
30
|
$:.unshift(File.dirname(__FILE__))
|
31
31
|
$:.unshift(File.dirname(__FILE__) + "/../../activerecord/lib")
|
@@ -305,6 +305,7 @@ module FeedTools
|
|
305
305
|
@feed_cache = DatabaseFeedCache
|
306
306
|
@user_agent = "FeedTools/#{FEED_TOOLS_VERSION} " +
|
307
307
|
"+http://www.sporkmonger.com/projects/feedtools/"
|
308
|
+
@no_content_string = "[no description]"
|
308
309
|
|
309
310
|
# Returns the current caching mechanism.
|
310
311
|
def FeedTools.feed_cache
|
@@ -377,6 +378,17 @@ module FeedTools
|
|
377
378
|
def FeedTools.user_agent=(new_user_agent)
|
378
379
|
@user_agent = new_user_agent
|
379
380
|
end
|
381
|
+
|
382
|
+
# Returns the currently used no content string.
|
383
|
+
def FeedTools.no_content_string
|
384
|
+
return @no_content_string
|
385
|
+
end
|
386
|
+
|
387
|
+
# Sets the no content string to use when a feed is missing a content element.
|
388
|
+
# Used only for xml output.
|
389
|
+
def FeedTools.no_content_string=(new_no_content_string)
|
390
|
+
@no_content_string = new_no_content_string
|
391
|
+
end
|
380
392
|
|
381
393
|
# Returns true if the html tidy module can be used.
|
382
394
|
#
|
@@ -548,11 +560,31 @@ module FeedTools
|
|
548
560
|
end
|
549
561
|
end
|
550
562
|
|
551
|
-
#
|
552
|
-
def FeedTools.
|
563
|
+
# Converts a url into a tag uri
|
564
|
+
def FeedTools.build_tag_uri(url, date)
|
565
|
+
unless url.kind_of? String
|
566
|
+
raise ArgumentError, "Expected String, got #{url.class.name}"
|
567
|
+
end
|
568
|
+
unless date.kind_of? Time
|
569
|
+
raise ArgumentError, "Expected Time, got #{date.class.name}"
|
570
|
+
end
|
571
|
+
tag_uri = normalize_url(url)
|
572
|
+
host = URI.parse(tag_uri).host
|
573
|
+
tag_uri.gsub!(/^(http|ftp|file):\/*/, "")
|
574
|
+
tag_uri.gsub!(/#/, "/")
|
575
|
+
tag_uri = "tag:#{host},#{date.strftime('%Y-%m-%d')}:" +
|
576
|
+
"#{tag_uri[(tag_uri.index(host) + host.size)..-1]}"
|
577
|
+
return tag_uri
|
578
|
+
end
|
579
|
+
|
580
|
+
# Returns true if the parameter appears to be a valid uri
|
581
|
+
def FeedTools.is_uri?(url)
|
553
582
|
return false if url.nil?
|
554
583
|
begin
|
555
584
|
uri = URI.parse(url)
|
585
|
+
if uri.scheme.nil? || uri.scheme == ""
|
586
|
+
return false
|
587
|
+
end
|
556
588
|
rescue URI::InvalidURIError
|
557
589
|
return false
|
558
590
|
end
|
@@ -699,8 +731,18 @@ module FeedTools
|
|
699
731
|
def FeedTools.build_merged_feed(url_array)
|
700
732
|
return nil if url_array.nil?
|
701
733
|
merged_feed = Feed.new
|
734
|
+
retrieved_feeds = []
|
735
|
+
feed_threads = []
|
702
736
|
url_array.each do |feed_url|
|
703
|
-
|
737
|
+
feed_threads << Thread.new do
|
738
|
+
feed = Feed.open(feed_url)
|
739
|
+
retrieved_feeds << feed
|
740
|
+
end
|
741
|
+
end
|
742
|
+
feed_threads.each do |thread|
|
743
|
+
thread.join
|
744
|
+
end
|
745
|
+
retrieved_feeds.each do |feed|
|
704
746
|
merged_feed.entries.concat(
|
705
747
|
feed.entries.collect do |entry|
|
706
748
|
entry.title = "#{feed.title}: #{entry.title}"
|
@@ -1508,7 +1550,7 @@ module FeedTools
|
|
1508
1550
|
end
|
1509
1551
|
end
|
1510
1552
|
if @link == "" || @link.nil?
|
1511
|
-
if FeedTools.
|
1553
|
+
if FeedTools.is_uri? self.guid
|
1512
1554
|
@link = self.guid
|
1513
1555
|
end
|
1514
1556
|
end
|
@@ -1562,7 +1604,7 @@ module FeedTools
|
|
1562
1604
|
if @icon == ""
|
1563
1605
|
@icon = FeedTools.unescape_entities(
|
1564
1606
|
XPath.first(icon_node, "text()").to_s)
|
1565
|
-
unless FeedTools.
|
1607
|
+
unless FeedTools.is_uri? @icon
|
1566
1608
|
@icon = ""
|
1567
1609
|
end
|
1568
1610
|
end
|
@@ -1581,19 +1623,20 @@ module FeedTools
|
|
1581
1623
|
def author
|
1582
1624
|
if @author.nil?
|
1583
1625
|
@author = FeedTools::Feed::Author.new
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1626
|
+
unless channel_node.nil?
|
1627
|
+
author_node = XPath.first(channel_node, "author")
|
1628
|
+
if author_node.nil?
|
1629
|
+
author_node = XPath.first(channel_node, "managingEditor")
|
1630
|
+
end
|
1631
|
+
if author_node.nil?
|
1632
|
+
author_node = XPath.first(channel_node, "dc:author")
|
1633
|
+
end
|
1634
|
+
if author_node.nil?
|
1635
|
+
author_node = XPath.first(channel_node, "dc:creator")
|
1636
|
+
end
|
1637
|
+
if author_node.nil?
|
1638
|
+
author_node = XPath.first(channel_node, "atom:author")
|
1639
|
+
end
|
1597
1640
|
end
|
1598
1641
|
unless author_node.nil?
|
1599
1642
|
@author.raw = FeedTools.unescape_entities(
|
@@ -1771,6 +1814,149 @@ module FeedTools
|
|
1771
1814
|
return @itunes_author
|
1772
1815
|
end
|
1773
1816
|
|
1817
|
+
# Returns the feed item time
|
1818
|
+
def time
|
1819
|
+
if @time.nil?
|
1820
|
+
unless channel_node.nil?
|
1821
|
+
time_string = XPath.first(channel_node, "pubDate/text()").to_s
|
1822
|
+
if time_string == ""
|
1823
|
+
time_string = XPath.first(channel_node, "dc:date/text()").to_s
|
1824
|
+
end
|
1825
|
+
if time_string == ""
|
1826
|
+
time_string = XPath.first(channel_node, "issued/text()").to_s
|
1827
|
+
end
|
1828
|
+
if time_string == ""
|
1829
|
+
time_string = XPath.first(channel_node, "updated/text()").to_s
|
1830
|
+
end
|
1831
|
+
if time_string == ""
|
1832
|
+
time_string = XPath.first(channel_node, "time/text()").to_s
|
1833
|
+
end
|
1834
|
+
end
|
1835
|
+
begin
|
1836
|
+
if time_string != nil && time_string != ""
|
1837
|
+
@time = Time.parse(time_string) rescue self.succ_time
|
1838
|
+
elsif time_string == nil
|
1839
|
+
@time = self.succ_time
|
1840
|
+
end
|
1841
|
+
if @time == nil
|
1842
|
+
@time = Time.now
|
1843
|
+
end
|
1844
|
+
rescue
|
1845
|
+
@time = Time.now
|
1846
|
+
end
|
1847
|
+
end
|
1848
|
+
return @time
|
1849
|
+
end
|
1850
|
+
|
1851
|
+
# Sets the feed item time
|
1852
|
+
def time=(new_time)
|
1853
|
+
@time = new_time
|
1854
|
+
end
|
1855
|
+
|
1856
|
+
# Returns 1 second after the previous item's time.
|
1857
|
+
def succ_time #:nodoc:
|
1858
|
+
begin
|
1859
|
+
if feed.nil?
|
1860
|
+
return nil
|
1861
|
+
end
|
1862
|
+
feed.items
|
1863
|
+
unsorted_items = feed.instance_variable_get("@items")
|
1864
|
+
item_index = unsorted_items.index(self)
|
1865
|
+
if item_index.nil?
|
1866
|
+
return nil
|
1867
|
+
end
|
1868
|
+
if item_index <= 0
|
1869
|
+
return Time.now
|
1870
|
+
end
|
1871
|
+
previous_item = unsorted_items[item_index - 1]
|
1872
|
+
return previous_item.time.succ
|
1873
|
+
rescue
|
1874
|
+
return nil
|
1875
|
+
end
|
1876
|
+
end
|
1877
|
+
private :succ_time
|
1878
|
+
|
1879
|
+
# Returns the feed item updated time
|
1880
|
+
def updated
|
1881
|
+
if @updated.nil?
|
1882
|
+
unless channel_node.nil?
|
1883
|
+
updated_string = XPath.first(channel_node, "updated/text()").to_s
|
1884
|
+
if updated_string == ""
|
1885
|
+
updated_string = XPath.first(channel_node, "modified/text()").to_s
|
1886
|
+
end
|
1887
|
+
end
|
1888
|
+
if updated_string != nil && updated_string != ""
|
1889
|
+
@updated = Time.parse(updated_string) rescue nil
|
1890
|
+
else
|
1891
|
+
@updated = nil
|
1892
|
+
end
|
1893
|
+
end
|
1894
|
+
return @updated
|
1895
|
+
end
|
1896
|
+
|
1897
|
+
# Sets the feed item updated time
|
1898
|
+
def updated=(new_updated)
|
1899
|
+
@updated = new_updated
|
1900
|
+
end
|
1901
|
+
|
1902
|
+
# Returns the feed item issued time
|
1903
|
+
def issued
|
1904
|
+
if @issued.nil?
|
1905
|
+
unless channel_node.nil?
|
1906
|
+
issued_string = XPath.first(channel_node, "issued/text()").to_s
|
1907
|
+
if issued_string == ""
|
1908
|
+
issued_string = XPath.first(channel_node, "pubDate/text()").to_s
|
1909
|
+
end
|
1910
|
+
if issued_string == ""
|
1911
|
+
issued_string = XPath.first(channel_node, "dc:date/text()").to_s
|
1912
|
+
end
|
1913
|
+
if issued_string == ""
|
1914
|
+
issued_string = XPath.first(channel_node, "published/text()").to_s
|
1915
|
+
end
|
1916
|
+
end
|
1917
|
+
if issued_string != nil && issued_string != ""
|
1918
|
+
@issued = Time.parse(issued_string) rescue nil
|
1919
|
+
else
|
1920
|
+
@issued = nil
|
1921
|
+
end
|
1922
|
+
end
|
1923
|
+
return @issued
|
1924
|
+
end
|
1925
|
+
|
1926
|
+
# Sets the feed item issued time
|
1927
|
+
def issued=(new_issued)
|
1928
|
+
@issued = new_issued
|
1929
|
+
end
|
1930
|
+
|
1931
|
+
# Returns the feed item published time
|
1932
|
+
def published
|
1933
|
+
if @published.nil?
|
1934
|
+
unless channel_node.nil?
|
1935
|
+
published_string = XPath.first(channel_node, "published/text()").to_s
|
1936
|
+
if published_string == ""
|
1937
|
+
published_string = XPath.first(channel_node, "pubDate/text()").to_s
|
1938
|
+
end
|
1939
|
+
if published_string == ""
|
1940
|
+
published_string = XPath.first(channel_node, "dc:date/text()").to_s
|
1941
|
+
end
|
1942
|
+
if published_string == ""
|
1943
|
+
published_string = XPath.first(channel_node, "issued/text()").to_s
|
1944
|
+
end
|
1945
|
+
end
|
1946
|
+
if published_string != nil && published_string != ""
|
1947
|
+
@published = Time.parse(published_string) rescue nil
|
1948
|
+
else
|
1949
|
+
@published = nil
|
1950
|
+
end
|
1951
|
+
end
|
1952
|
+
return @published
|
1953
|
+
end
|
1954
|
+
|
1955
|
+
# Sets the feed item published time
|
1956
|
+
def published=(new_published)
|
1957
|
+
@published = new_published
|
1958
|
+
end
|
1959
|
+
|
1774
1960
|
# Returns a list of the feed's categories
|
1775
1961
|
def categories
|
1776
1962
|
if @categories.nil?
|
@@ -1889,15 +2075,20 @@ module FeedTools
|
|
1889
2075
|
# Returns the feed's copyright information
|
1890
2076
|
def copyright
|
1891
2077
|
if @copyright.nil?
|
1892
|
-
|
1893
|
-
|
1894
|
-
@copyright
|
1895
|
-
|
1896
|
-
|
1897
|
-
@copyright
|
2078
|
+
unless channel_node.nil?
|
2079
|
+
@copyright = XPath.first(channel_node, "copyright/text()").to_s
|
2080
|
+
if @copyright == ""
|
2081
|
+
@copyright = XPath.first(channel_node, "rights/text()").to_s
|
2082
|
+
end
|
2083
|
+
if @copyright == ""
|
2084
|
+
@copyright = XPath.first(channel_node, "dc:rights/text()").to_s
|
2085
|
+
end
|
2086
|
+
if @copyright == ""
|
2087
|
+
@copyright = XPath.first(channel_node, "copyrights/text()").to_s
|
2088
|
+
end
|
2089
|
+
@copyright = FeedTools.sanitize_html(@copyright, :strip)
|
2090
|
+
@copyright = nil if @copyright == ""
|
1898
2091
|
end
|
1899
|
-
@copyright = FeedTools.sanitize_html(@copyright, :strip)
|
1900
|
-
@copyright = nil if @copyright == ""
|
1901
2092
|
end
|
1902
2093
|
return @copyright
|
1903
2094
|
end
|
@@ -2335,7 +2526,7 @@ module FeedTools
|
|
2335
2526
|
end
|
2336
2527
|
end
|
2337
2528
|
end
|
2338
|
-
elsif feed_type == "atom"
|
2529
|
+
elsif feed_type == "atom" && version == 0.3
|
2339
2530
|
# normal atom format
|
2340
2531
|
return xml_builder.feed("xmlns" => "http://purl.org/atom/ns#",
|
2341
2532
|
"version" => version,
|
@@ -2345,6 +2536,19 @@ module FeedTools
|
|
2345
2536
|
"mode" => "escaped",
|
2346
2537
|
"type" => "text/html")
|
2347
2538
|
end
|
2539
|
+
xml_builder.author do
|
2540
|
+
unless self.author.nil? || self.author.name.nil?
|
2541
|
+
xml_builder.name(self.author.name)
|
2542
|
+
else
|
2543
|
+
xml_builder.name("n/a")
|
2544
|
+
end
|
2545
|
+
unless self.author.nil? || self.author.email.nil?
|
2546
|
+
xml_builder.email(self.author.email)
|
2547
|
+
end
|
2548
|
+
unless self.author.nil? || self.author.url.nil?
|
2549
|
+
xml_builder.url(self.author.url)
|
2550
|
+
end
|
2551
|
+
end
|
2348
2552
|
unless link.nil? || link == ""
|
2349
2553
|
xml_builder.link("href" => link,
|
2350
2554
|
"rel" => "alternate",
|
@@ -2365,6 +2569,74 @@ module FeedTools
|
|
2365
2569
|
end
|
2366
2570
|
end
|
2367
2571
|
end
|
2572
|
+
elsif feed_type == "atom" && version == 1.0
|
2573
|
+
# normal atom format
|
2574
|
+
return xml_builder.feed("xmlns" => "http://www.w3.org/2005/Atom",
|
2575
|
+
"xml:lang" => language) do
|
2576
|
+
unless title.nil? || title == ""
|
2577
|
+
xml_builder.title(title,
|
2578
|
+
"type" => "html")
|
2579
|
+
end
|
2580
|
+
xml_builder.author do
|
2581
|
+
unless self.author.nil? || self.author.name.nil?
|
2582
|
+
xml_builder.name(self.author.name)
|
2583
|
+
else
|
2584
|
+
xml_builder.name("n/a")
|
2585
|
+
end
|
2586
|
+
unless self.author.nil? || self.author.email.nil?
|
2587
|
+
xml_builder.email(self.author.email)
|
2588
|
+
end
|
2589
|
+
unless self.author.nil? || self.author.url.nil?
|
2590
|
+
xml_builder.url(self.author.url)
|
2591
|
+
end
|
2592
|
+
end
|
2593
|
+
unless self.url.nil? || self.url == ""
|
2594
|
+
xml_builder.link("href" => self.url,
|
2595
|
+
"rel" => "self",
|
2596
|
+
"type" => "application/atom+xml")
|
2597
|
+
end
|
2598
|
+
unless self.link.nil? || self.link == ""
|
2599
|
+
xml_builder.link("href" => self.link,
|
2600
|
+
"rel" => "alternate",
|
2601
|
+
"type" => "text/html",
|
2602
|
+
"title" => self.title)
|
2603
|
+
end
|
2604
|
+
unless description.nil? || description == ""
|
2605
|
+
xml_builder.subtitle(description,
|
2606
|
+
"type" => "html")
|
2607
|
+
else
|
2608
|
+
xml_builder.subtitle(FeedTools.no_content_string,
|
2609
|
+
"type" => "html")
|
2610
|
+
end
|
2611
|
+
if self.updated != nil
|
2612
|
+
xml_builder.updated(self.updated.iso8601)
|
2613
|
+
elsif self.time != nil
|
2614
|
+
# Not technically correct, but a heck of a lot better
|
2615
|
+
# than the Time.now fall-back.
|
2616
|
+
xml_builder.updated(self.time.iso8601)
|
2617
|
+
else
|
2618
|
+
xml_builder.updated(Time.now.iso8601)
|
2619
|
+
end
|
2620
|
+
unless self.published.nil?
|
2621
|
+
xml_builder.published(self.published.iso8601)
|
2622
|
+
end
|
2623
|
+
xml_builder.generator("FeedTools - " +
|
2624
|
+
"http://www.sporkmonger.com/projects/feedtools")
|
2625
|
+
unless self.id.nil?
|
2626
|
+
unless FeedTools.is_uri? self.id
|
2627
|
+
raise "The unique id must be a URI."
|
2628
|
+
end
|
2629
|
+
xml_builder.id(self.id)
|
2630
|
+
else
|
2631
|
+
raise "Cannot build feed, missing feed unique id."
|
2632
|
+
end
|
2633
|
+
build_xml_hook(feed_type, version, xml_builder)
|
2634
|
+
unless items.nil?
|
2635
|
+
for item in items
|
2636
|
+
item.build_xml(feed_type, version, xml_builder)
|
2637
|
+
end
|
2638
|
+
end
|
2639
|
+
end
|
2368
2640
|
end
|
2369
2641
|
end
|
2370
2642
|
|
@@ -2678,6 +2950,15 @@ module FeedTools
|
|
2678
2950
|
unless root_node.nil?
|
2679
2951
|
repair_entities = false
|
2680
2952
|
description_node = XPath.first(root_node, "description")
|
2953
|
+
if description_node.nil?
|
2954
|
+
description_node = XPath.first(root_node, "content:encoded")
|
2955
|
+
end
|
2956
|
+
if description_node.nil?
|
2957
|
+
description_node = XPath.first(root_node, "content")
|
2958
|
+
end
|
2959
|
+
if description_node.nil?
|
2960
|
+
description_node = XPath.first(root_node, "fullitem")
|
2961
|
+
end
|
2681
2962
|
if description_node.nil?
|
2682
2963
|
description_node = XPath.first(root_node, "xhtml:body")
|
2683
2964
|
end
|
@@ -2699,15 +2980,6 @@ module FeedTools
|
|
2699
2980
|
if description_node.nil?
|
2700
2981
|
description_node = XPath.first(root_node, "ABSTRACT")
|
2701
2982
|
end
|
2702
|
-
if description_node.nil?
|
2703
|
-
description_node = XPath.first(root_node, "content:encoded")
|
2704
|
-
end
|
2705
|
-
if description_node.nil?
|
2706
|
-
description_node = XPath.first(root_node, "content")
|
2707
|
-
end
|
2708
|
-
if description_node.nil?
|
2709
|
-
description_node = XPath.first(root_node, "fullitem")
|
2710
|
-
end
|
2711
2983
|
if description_node.nil?
|
2712
2984
|
description_node = XPath.first(root_node, "info")
|
2713
2985
|
@bozo = true unless description_node.nil?
|
@@ -2853,7 +3125,7 @@ module FeedTools
|
|
2853
3125
|
end
|
2854
3126
|
end
|
2855
3127
|
if @link == "" || @link.nil?
|
2856
|
-
if FeedTools.
|
3128
|
+
if FeedTools.is_uri? self.guid
|
2857
3129
|
@link = self.guid
|
2858
3130
|
end
|
2859
3131
|
end
|
@@ -3016,9 +3288,20 @@ module FeedTools
|
|
3016
3288
|
# Returns the feed item's copyright information
|
3017
3289
|
def copyright
|
3018
3290
|
if @copyright.nil?
|
3019
|
-
|
3020
|
-
|
3021
|
-
|
3291
|
+
unless root_node.nil?
|
3292
|
+
@copyright = XPath.first(root_node, "dc:rights/text()").to_s
|
3293
|
+
if @copyright == ""
|
3294
|
+
@copyright = XPath.first(root_node, "rights/text()").to_s
|
3295
|
+
end
|
3296
|
+
if @copyright == ""
|
3297
|
+
@copyright = XPath.first(root_node, "copyright/text()").to_s
|
3298
|
+
end
|
3299
|
+
if @copyright == ""
|
3300
|
+
@copyright = XPath.first(root_node, "copyrights/text()").to_s
|
3301
|
+
end
|
3302
|
+
@copyright = FeedTools.sanitize_html(@copyright, :strip)
|
3303
|
+
@copyright = nil if @copyright == ""
|
3304
|
+
end
|
3022
3305
|
end
|
3023
3306
|
return @copyright
|
3024
3307
|
end
|
@@ -3400,19 +3683,20 @@ module FeedTools
|
|
3400
3683
|
def author
|
3401
3684
|
if @author.nil?
|
3402
3685
|
@author = FeedTools::Feed::Author.new
|
3403
|
-
|
3404
|
-
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
|
3409
|
-
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3413
|
-
|
3414
|
-
|
3415
|
-
|
3686
|
+
unless root_node.nil?
|
3687
|
+
author_node = XPath.first(root_node, "author")
|
3688
|
+
if author_node.nil?
|
3689
|
+
author_node = XPath.first(root_node, "managingEditor")
|
3690
|
+
end
|
3691
|
+
if author_node.nil?
|
3692
|
+
author_node = XPath.first(root_node, "dc:author")
|
3693
|
+
end
|
3694
|
+
if author_node.nil?
|
3695
|
+
author_node = XPath.first(root_node, "dc:creator")
|
3696
|
+
end
|
3697
|
+
if author_node.nil?
|
3698
|
+
author_node = XPath.first(root_node, "atom:author")
|
3699
|
+
end
|
3416
3700
|
end
|
3417
3701
|
unless author_node.nil?
|
3418
3702
|
@author.raw = FeedTools.unescape_entities(
|
@@ -3621,14 +3905,22 @@ module FeedTools
|
|
3621
3905
|
# Returns the feed item time
|
3622
3906
|
def time
|
3623
3907
|
if @time.nil?
|
3624
|
-
|
3625
|
-
|
3626
|
-
time_string
|
3627
|
-
|
3628
|
-
|
3629
|
-
time_string
|
3908
|
+
unless root_node.nil?
|
3909
|
+
time_string = XPath.first(root_node, "pubDate/text()").to_s
|
3910
|
+
if time_string == ""
|
3911
|
+
time_string = XPath.first(root_node, "dc:date/text()").to_s
|
3912
|
+
end
|
3913
|
+
if time_string == ""
|
3914
|
+
time_string = XPath.first(root_node, "issued/text()").to_s
|
3915
|
+
end
|
3916
|
+
if time_string == ""
|
3917
|
+
time_string = XPath.first(root_node, "updated/text()").to_s
|
3918
|
+
end
|
3919
|
+
if time_string == ""
|
3920
|
+
time_string = XPath.first(root_node, "time/text()").to_s
|
3921
|
+
end
|
3630
3922
|
end
|
3631
|
-
if time_string != ""
|
3923
|
+
if time_string != nil && time_string != ""
|
3632
3924
|
@time = Time.parse(time_string) rescue Time.now
|
3633
3925
|
elsif time_string == nil
|
3634
3926
|
@time = Time.now
|
@@ -3641,7 +3933,59 @@ module FeedTools
|
|
3641
3933
|
def time=(new_time)
|
3642
3934
|
@time = new_time
|
3643
3935
|
end
|
3936
|
+
|
3937
|
+
# Returns the feed item updated time
|
3938
|
+
def updated
|
3939
|
+
if @updated.nil?
|
3940
|
+
unless root_node.nil?
|
3941
|
+
updated_string = XPath.first(root_node, "updated/text()").to_s
|
3942
|
+
if updated_string == ""
|
3943
|
+
updated_string = XPath.first(root_node, "modified/text()").to_s
|
3944
|
+
end
|
3945
|
+
end
|
3946
|
+
if updated_string != nil && updated_string != ""
|
3947
|
+
@updated = Time.parse(updated_string) rescue nil
|
3948
|
+
else
|
3949
|
+
@updated = nil
|
3950
|
+
end
|
3951
|
+
end
|
3952
|
+
return @updated
|
3953
|
+
end
|
3954
|
+
|
3955
|
+
# Sets the feed item updated time
|
3956
|
+
def updated=(new_updated)
|
3957
|
+
@updated = new_updated
|
3958
|
+
end
|
3959
|
+
|
3960
|
+
# Returns the feed item issued time
|
3961
|
+
def issued
|
3962
|
+
if @issued.nil?
|
3963
|
+
unless root_node.nil?
|
3964
|
+
issued_string = XPath.first(root_node, "issued/text()").to_s
|
3965
|
+
if issued_string == ""
|
3966
|
+
issued_string = XPath.first(root_node, "published/text()").to_s
|
3967
|
+
end
|
3968
|
+
if issued_string == ""
|
3969
|
+
issued_string = XPath.first(root_node, "pubDate/text()").to_s
|
3970
|
+
end
|
3971
|
+
if issued_string == ""
|
3972
|
+
issued_string = XPath.first(root_node, "dc:date/text()").to_s
|
3973
|
+
end
|
3974
|
+
end
|
3975
|
+
if issued_string != nil && issued_string != ""
|
3976
|
+
@issued = Time.parse(issued_string) rescue nil
|
3977
|
+
else
|
3978
|
+
@issued = nil
|
3979
|
+
end
|
3980
|
+
end
|
3981
|
+
return @issued
|
3982
|
+
end
|
3644
3983
|
|
3984
|
+
# Sets the feed item issued time
|
3985
|
+
def issued=(new_issued)
|
3986
|
+
@issued = new_issued
|
3987
|
+
end
|
3988
|
+
|
3645
3989
|
# Returns the url for posting comments
|
3646
3990
|
def comments
|
3647
3991
|
if @comments.nil?
|
@@ -3837,7 +4181,7 @@ module FeedTools
|
|
3837
4181
|
end
|
3838
4182
|
build_xml_hook(feed_type, version, xml_builder)
|
3839
4183
|
end
|
3840
|
-
elsif feed_type == "atom"
|
4184
|
+
elsif feed_type == "atom" && version == 0.3
|
3841
4185
|
# normal atom format
|
3842
4186
|
return xml_builder.entry("xmlns" => "http://purl.org/atom/ns#") do
|
3843
4187
|
unless title.nil? || title == ""
|
@@ -3845,6 +4189,19 @@ module FeedTools
|
|
3845
4189
|
"mode" => "escaped",
|
3846
4190
|
"type" => "text/html")
|
3847
4191
|
end
|
4192
|
+
xml_builder.author do
|
4193
|
+
unless self.author.nil? || self.author.name.nil?
|
4194
|
+
xml_builder.name(self.author.name)
|
4195
|
+
else
|
4196
|
+
xml_builder.name("n/a")
|
4197
|
+
end
|
4198
|
+
unless self.author.nil? || self.author.email.nil?
|
4199
|
+
xml_builder.email(self.author.email)
|
4200
|
+
end
|
4201
|
+
unless self.author.nil? || self.author.url.nil?
|
4202
|
+
xml_builder.url(self.author.url)
|
4203
|
+
end
|
4204
|
+
end
|
3848
4205
|
unless link.nil? || link == ""
|
3849
4206
|
xml_builder.link("href" => link,
|
3850
4207
|
"rel" => "alternate",
|
@@ -3866,6 +4223,74 @@ module FeedTools
|
|
3866
4223
|
end
|
3867
4224
|
build_xml_hook(feed_type, version, xml_builder)
|
3868
4225
|
end
|
4226
|
+
elsif feed_type == "atom" && version == 1.0
|
4227
|
+
# normal atom format
|
4228
|
+
return xml_builder.entry("xmlns" => "http://www.w3.org/2005/Atom") do
|
4229
|
+
unless title.nil? || title == ""
|
4230
|
+
xml_builder.title(title,
|
4231
|
+
"type" => "html")
|
4232
|
+
end
|
4233
|
+
xml_builder.author do
|
4234
|
+
unless self.author.nil? || self.author.name.nil?
|
4235
|
+
xml_builder.name(self.author.name)
|
4236
|
+
else
|
4237
|
+
xml_builder.name("n/a")
|
4238
|
+
end
|
4239
|
+
unless self.author.nil? || self.author.email.nil?
|
4240
|
+
xml_builder.email(self.author.email)
|
4241
|
+
end
|
4242
|
+
unless self.author.nil? || self.author.url.nil?
|
4243
|
+
xml_builder.url(self.author.url)
|
4244
|
+
end
|
4245
|
+
end
|
4246
|
+
unless link.nil? || link == ""
|
4247
|
+
xml_builder.link("href" => link,
|
4248
|
+
"rel" => "alternate",
|
4249
|
+
"type" => "text/html",
|
4250
|
+
"title" => title)
|
4251
|
+
end
|
4252
|
+
unless description.nil? || description == ""
|
4253
|
+
xml_builder.content(description,
|
4254
|
+
"type" => "html")
|
4255
|
+
else
|
4256
|
+
xml_builder.content(FeedTools.no_content_string,
|
4257
|
+
"type" => "html")
|
4258
|
+
end
|
4259
|
+
if self.updated != nil
|
4260
|
+
xml_builder.updated(self.updated.iso8601)
|
4261
|
+
elsif self.time != nil
|
4262
|
+
# Not technically correct, but a heck of a lot better
|
4263
|
+
# than the Time.now fall-back.
|
4264
|
+
xml_builder.updated(self.time.iso8601)
|
4265
|
+
else
|
4266
|
+
xml_builder.updated(Time.now.iso8601)
|
4267
|
+
end
|
4268
|
+
unless self.published.nil?
|
4269
|
+
xml_builder.published(self.published.iso8601)
|
4270
|
+
end
|
4271
|
+
if self.id != nil
|
4272
|
+
unless FeedTools.is_uri? self.id
|
4273
|
+
if self.time != nil && self.link != nil
|
4274
|
+
xml_builder.id(FeedTools.build_tag_uri(self.link, self.time))
|
4275
|
+
else
|
4276
|
+
raise "The unique id must be a URI. " +
|
4277
|
+
"(Attempted to generate id, but failed.)"
|
4278
|
+
end
|
4279
|
+
else
|
4280
|
+
xml_builder.id(self.id)
|
4281
|
+
end
|
4282
|
+
elsif self.time != nil && self.link != nil
|
4283
|
+
xml_builder.id(FeedTools.build_tag_uri(self.link, self.time))
|
4284
|
+
else
|
4285
|
+
raise "Cannot build feed, missing feed unique id."
|
4286
|
+
end
|
4287
|
+
unless self.tags.nil? || self.tags.size == 0
|
4288
|
+
for tag in self.tags
|
4289
|
+
xml_builder.category("term" => tag)
|
4290
|
+
end
|
4291
|
+
end
|
4292
|
+
build_xml_hook(feed_type, version, xml_builder)
|
4293
|
+
end
|
3869
4294
|
end
|
3870
4295
|
end
|
3871
4296
|
|
@@ -3881,6 +4306,8 @@ module FeedTools
|
|
3881
4306
|
alias_method :content=, :description=
|
3882
4307
|
alias_method :guid, :id
|
3883
4308
|
alias_method :guid=, :id=
|
4309
|
+
alias_method :published, :issued
|
4310
|
+
alias_method :published=, :issued=
|
3884
4311
|
end
|
3885
4312
|
end
|
3886
4313
|
|
data/rakefile
CHANGED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: feedtools
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.
|
7
|
-
date: 2005-09-
|
6
|
+
version: 0.2.7
|
7
|
+
date: 2005-09-02 00:00:00 -04:00
|
8
8
|
summary: "Parsing, generation, and caching system for xml news feeds."
|
9
9
|
require_paths:
|
10
10
|
- lib
|