Skip to content

Commit c4d4c98

Browse files
committed
Load XML-Feed-0.12 into trunk.
1 parent 4679cf3 commit c4d4c98

File tree

9 files changed

+236
-20
lines changed

9 files changed

+236
-20
lines changed

Changes

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
# $Id: Changes 1956 2006-08-08 04:34:54Z btrott $
1+
# $Id: Changes 1958 2006-08-14 05:31:27Z btrott $
22

33
Revision history for XML::Feed
44

5+
0.12 2006.08.13
6+
- Generate Atom 1.0 feeds by default. Thanks to Tatsuhiko Miyagawa for
7+
the patch.
8+
59
0.11 2006.08.07
610
- Fixed a bug in XML::Feed::Atom where entry->link and feed->link didn't
711
return the proper link element if the "rel" attribute wasn't defined for

MANIFEST

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ t/01-parse.t
3030
t/02-create.t
3131
t/04-splice.t
3232
t/05-atom10-link.t
33+
t/06-atom10.t
34+
t/07-atom10-create.t
3335
t/samples/atom-10-example.xml
36+
t/samples/atom-full.xml
3437
t/samples/atom.xml
3538
t/samples/rss10-invalid-date.xml
3639
t/samples/rss10.xml

META.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ requires:
2323
URI::Fetch: 0
2424
XML::Atom: 0.08
2525
XML::RSS: 1.01
26-
version: 0.11
26+
version: 0.12

lib/XML/Feed.pm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: Feed.pm 1956 2006-08-08 04:34:54Z btrott $
1+
# $Id: Feed.pm 1958 2006-08-14 05:31:27Z btrott $
22

33
package XML::Feed;
44
use strict;
@@ -8,7 +8,7 @@ use Feed::Find;
88
use URI::Fetch;
99
use Carp;
1010

11-
our $VERSION = '0.11';
11+
our $VERSION = '0.12';
1212

1313
sub new {
1414
my $class = shift;

lib/XML/Feed/Atom.pm

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: Atom.pm 1955 2006-08-02 05:59:58Z btrott $
1+
# $Id: Atom.pm 1958 2006-08-14 05:31:27Z btrott $
22

33
package XML::Feed::Atom;
44
use strict;
@@ -11,7 +11,7 @@ use DateTime::Format::W3CDTF;
1111

1212
sub init_empty {
1313
my $feed = shift;
14-
$feed->{atom} = XML::Atom::Feed->new;
14+
$feed->{atom} = XML::Atom::Feed->new(Version => 1.0);
1515
$feed;
1616
}
1717

@@ -46,7 +46,7 @@ sub generator { shift->{atom}->generator(@_) }
4646
sub author {
4747
my $feed = shift;
4848
if (@_ && $_[0]) {
49-
my $person = XML::Atom::Person->new;
49+
my $person = XML::Atom::Person->new(Version => 1.0);
5050
$person->name($_[0]);
5151
$feed->{atom}->author($person);
5252
} else {
@@ -59,15 +59,16 @@ sub modified {
5959
if (@_) {
6060
$feed->{atom}->modified(DateTime::Format::W3CDTF->format_datetime($_[0]));
6161
} else {
62-
iso2dt($feed->{atom}->modified);
62+
$feed->{atom}->modified ? iso2dt($feed->{atom}->modified) : undef;
6363
}
6464
}
6565

66-
sub entries {
66+
sub entries {
6767
my @entries;
6868
for my $entry ($_[0]->{atom}->entries) {
6969
push @entries, XML::Feed::Entry::Atom->wrap($entry);
7070
}
71+
7172
@entries;
7273
}
7374

@@ -90,7 +91,7 @@ use List::Util qw( first );
9091

9192
sub init_empty {
9293
my $entry = shift;
93-
$entry->{entry} = XML::Atom::Entry->new;
94+
$entry->{entry} = XML::Atom::Entry->new(Version => 1.0);
9495
1;
9596
}
9697

@@ -112,7 +113,7 @@ sub summary {
112113
$entry->{entry}->summary(ref($_[0]) eq 'XML::Feed::Content' ?
113114
$_[0]->body : $_[0]);
114115
} else {
115-
XML::Feed::Content->wrap({ type => 'text/html',
116+
XML::Feed::Content->wrap({ type => 'html',
116117
body => $entry->{entry}->summary });
117118
}
118119
}
@@ -122,14 +123,22 @@ sub content {
122123
if (@_) {
123124
my %param;
124125
if (ref($_[0]) eq 'XML::Feed::Content') {
125-
%param = (Body => $_[0]->body, Type => $_[0]->type || 'text/html');
126+
%param = (Body => $_[0]->body);
126127
} else {
127-
%param = (Body => $_[0], Type => 'text/html');
128+
%param = (Body => $_[0]);
128129
}
129-
$entry->{entry}->content(XML::Atom::Content->new(%param));
130+
$entry->{entry}->content(XML::Atom::Content->new(%param, Version => 1.0));
130131
} else {
131132
my $c = $entry->{entry}->content;
132-
XML::Feed::Content->wrap({ type => $c ? $c->type : undef,
133+
134+
# map Atom types to MIME types
135+
my $type = $c ? $c->type : undef;
136+
if ($type) {
137+
$type = 'text/html' if $type eq 'xhtml' || $type eq 'html';
138+
$type = 'text/plain' if $type eq 'text';
139+
}
140+
141+
XML::Feed::Content->wrap({ type => $type,
133142
body => $c ? $c->body : undef });
134143
}
135144
}
@@ -138,16 +147,17 @@ sub category {
138147
my $entry = shift;
139148
my $ns = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/');
140149
if (@_) {
141-
$entry->{entry}->set($ns, 'subject', $_[0]);
150+
$entry->{entry}->add_category({ term => $_[0] });
142151
} else {
143-
$entry->{entry}->get($ns, 'subject');
152+
my $category = $entry->{entry}->category;
153+
$category ? ($category->label || $category->term) : $entry->{entry}->get($ns, 'subject');
144154
}
145155
}
146156

147157
sub author {
148158
my $entry = shift;
149159
if (@_ && $_[0]) {
150-
my $person = XML::Atom::Person->new;
160+
my $person = XML::Atom::Person->new(Version => 1.0);
151161
$person->name($_[0]);
152162
$entry->{entry}->author($person);
153163
} else {

t/04-splice.t

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# $Id: 04-splice.t 1872 2005-08-12 04:28:42Z btrott $
1+
# $Id: 04-splice.t 1958 2006-08-14 05:31:27Z btrott $
22

33
use strict;
44
use Test::More tests => 3;
55
use XML::Feed;
66

77
my $feed = XML::Feed->new('Atom');
88

9-
my $other = XML::Feed->parse('t/samples/atom.xml');
9+
my $other = XML::Feed->parse('t/samples/atom.xml')->convert('Atom');
1010
$feed->splice($other);
1111
is(scalar $feed->entries, 2, '2 entries in the feed after splicing');
1212

t/06-atom10.t

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use strict;
2+
use XML::Feed;
3+
4+
use Test::More;
5+
plan tests => 7;
6+
7+
my $feed = XML::Feed->parse("t/samples/atom-full.xml");
8+
is $feed->title, 'Content Considered Harmful Atom Feed';
9+
is $feed->link, 'http://blog.jrock.us/', "link without rel";
10+
11+
my $e = ($feed->entries)[0];
12+
ok $e->link, 'entry link without rel';
13+
is $e->category, "Catalyst", "atom:category support";
14+
is $e->modified, "2006-08-09T19:07:58", "atom:updated";
15+
is $e->content->type, 'text/html';
16+
like $e->content->body, qr/^<div class="pod">/;
17+
18+
19+

t/07-atom10-create.t

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use strict;
2+
use Test::More;
3+
4+
plan 'no_plan';
5+
6+
use XML::Feed;
7+
8+
my $feed = XML::Feed->new('Atom');
9+
$feed->title("foo");
10+
$feed->description("Atom 1.0 feed");
11+
$feed->link("http://example.org/");
12+
13+
my $entry = XML::Feed::Entry->new('Atom');
14+
$entry->title("1st Entry");
15+
$entry->link("http://example.org/");
16+
$entry->category("blah");
17+
$entry->content("<p>Hello world.</p>");
18+
19+
$feed->add_entry($entry);
20+
21+
my $xml = $feed->as_xml;
22+
like $xml, qr!<feed xmlns="http://www.w3.org/2005/Atom"!;
23+
like $xml, qr!<content .*type="xhtml">!;
24+
like $xml, qr!<div xmlns="http://www.w3.org/1999/xhtml">!;
25+
26+
# roundtrip
27+
$feed = XML::Feed->parse(\$xml);
28+
is $feed->format, 'Atom';
29+
is $feed->title, "foo";
30+
is $feed->description, "Atom 1.0 feed";
31+
is $feed->link, "http://example.org/";
32+
33+
my @entries = $feed->entries;
34+
is @entries, 1;
35+
$entry = $entries[0];
36+
37+
is $entry->title, '1st Entry';
38+
is $entry->link, 'http://example.org/';
39+
is $entry->category, 'blah';
40+
is $entry->content->type, 'text/html';
41+
like $entry->content->body, qr!\s*<p>Hello world.</p>\s*!s;
42+
43+
44+

t/samples/atom-full.xml

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?xml version="1.0" encoding="us-ascii"?>
2+
<feed xmlns="http://www.w3.org/2005/Atom"><title>Content Considered Harmful Atom Feed</title><id>http://blog.jrock.us/</id><link href="http://blog.jrock.us/feeds/category/Catalyst/xml" rel="self"/><link href="http://blog.jrock.us/"/><subtitle type="html">This is Jonathan Rockway&#39;s Blog, quite possibily the best blog ever.
3+
Or something.
4+
</subtitle><generator uri="http://www.jrock.us/" version="0.01_01">AngerWhale</generator><updated>2006-08-10T02:43:00Z</updated><entry><title>Catalyst + Cache</title><author><name>Jonathan T. Rockway</name><email>[email protected]</email></author><id>urn:guid:8D9B9CBE-27DB-11DB-B6C2-F007B8516AA5</id><link href="http://blog.jrock.us/articles/Catalyst%20+%20Cache.pod"/><category term="Catalyst" scheme="http://blog.jrock.us/categories/"/><updated>2006-08-09T19:07:58Z</updated><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><div class="pod">
5+
<p>I recently posted this to the <cite>Template::Toolkit</cite> mailing list, but
6+
the moderator rejected it for some reason. (Probably because <code>&lt;jon-perl-list-templates AT jrock.us&gt;</code> is the address that's
7+
subscribed, not <code>&lt;jon AT jrock.us&gt;</code>.)</p>
8+
<p>Anyway, here it is. I will expand on this further with actual
9+
measurements, but this will have to do for now.</p>
10+
<h4 id="Original_Message">Original Message</h4>
11+
<div id="Original_Message_CONTENT">
12+
<p><i>Thank you, you raise a good point that I had not fully considered. My
13+
goal is to display a dynamically generated page, but where most of the
14+
&quot;dynamic&quot; content is actually static for a period amount of time.
15+
(Take a news page, for example, where the list of news stories updates
16+
once an hour.)</i></p>
17+
18+
</div>
19+
<h4 id="My_Reply">My Reply</h4>
20+
<div id="My_Reply_CONTENT">
21+
<p>I have a similar problem with my blogging software. Most of the content
22+
is static, and it's kind of a waste to regenerate everything every time
23+
someone views the page. My solution to this problem is to use a
24+
<cite>Cache::FastMmap</cite> object to store the formatted HTML content of each post,
25+
keyed on the source material's MD5sum (and filetype, for reasons not
26+
relevant to this discussion :) </p>
27+
<p>This results in a nice speedup, since certain HTML filters are slow
28+
(OO.org document -&gt; HTML, for example).</p>
29+
<p>I also cache full pages, after they've been assembled by TT, keyed on
30+
the md5sum of each included article and some metadata (comment count,
31+
tags, etc.) The end result is a 5-20x speed up. With Catalyst's
32+
embedded server, I can do about 5 requests per second without cache, but
33+
it goes up to about 40-50 requests/second with the cache. So obviously
34+
a speedup. (And I'm still not doing a very good job, this was just a 20
35+
minute hack!)</p>
36+
<p>For the gory details, check out the code here:</p>
37+
<p><a href="http://www.jrock.us/trac/blog_software/browser/lib/Blog/Controller/Root.pm#L105">http://www.jrock.us/trac/blog_software/browser/lib/Blog/Controller/Root.pm#L105</a>
38+
(page cache)</p>
39+
<p>and:
40+
<a href="http://www.jrock.us/trac/blog_software/browser/lib/Blog/Model/Filesystem/Item.pm#L355">http://www.jrock.us/trac/blog_software/browser/lib/Blog/Model/Filesystem/Item.pm#L355</a>
41+
(object cache)</p>
42+
43+
44+
45+
46+
<p>Another caching strategy is to set dynamic pages to be cachable for say,
47+
10 seconds, and then letting Apache's mod_cache (experimental in 2.2.3,
48+
but it works for me) do the hard work. Your application gets hit once
49+
every ten seconds to refresh Apache's cache, but all the end-user
50+
requests are handled by serving from Apache's memory cache. With
51+
mpm_worker, it's *super fast*, and a 10 second update delay isn't bad.</p>
52+
<p>If your application is really slow, this will let you increase your
53+
slashdot resistance factor (as I call it) enormously. A quick ab
54+
against some cached content gave me a requests/per second rate of
55+
1638... much better than whatever your app would do by itself.</p>
56+
<p>And you don't really lose much by taking this approach, other than a 10
57+
second delay with your articles going live... but 10 seconds is nothing
58+
if you're getting 1500 requests per second and handling it with an old
59+
PIII :) </p>
60+
<p>If this info is useful to anyone else, let me know (off-list) and I'll
61+
write up a more detailed article about it :) </p>
62+
63+
</div>
64+
</div></div></content></entry><entry><title>Quantum Physics and the Template Toolkit</title><author><name>Jonathan T. Rockway</name><email>[email protected]</email></author><id>urn:guid:BB054AF0-2601-11DB-9738-946FBD312859</id><link href="http://blog.jrock.us/articles/Quantum%20Physics%20and%20the%20Template%20Toolkit.pod"/><category term="Catalyst" scheme="http://blog.jrock.us/categories/"/><category term="Programming" scheme="http://blog.jrock.us/categories/"/><updated>2006-08-07T10:44:20Z</updated><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><div class="pod">
65+
<p>As a programmer, you probably don't spend a lot of time thinking about
66+
the similarities between programming and quantum physics. Fortunately
67+
for us Perl users, some people <i>do</i> spend a lot of time thinking
68+
about physics, and they even wrap up the results in
69+
<a href="http://search.cpan.org">CPAN</a> modules for us!</p>
70+
<p>One such module is <cite>Quantum::Superpositions</cite>, which let me easily add
71+
some nice functionality to my <a href="http://www.jrock.us/trac/blog_software">blog software</a> the other day. </p>
72+
<p>As you can see (if you're looking at this article on my blog, not in
73+
an RSS reader), I have a list of tags to the left of my main content.
74+
If you click one, it shows you a list of articles that have been
75+
tagged with that tag. If you select more than one tag, you get this
76+
intersection of the two sets (tag1 AND tag2).</p>
77+
<p>That's nice, but I like to use the left navigation bar to show the
78+
user where he is <i>in addition to</i> letting him move somewhere else.
79+
To do this, I bold the current location, and remove the link. That
80+
way, the user won't try to visit the page he's already looking at.
81+
This is pretty simple to implement for things like the &quot;home page&quot; or
82+
the &quot;archives&quot;. You just check the current page, and if the link
83+
you're about to print out matches, make it bold instead. That logic
84+
looks something like this:</p>
85+
<pre> [% FOREACH category = categories %]
86+
[% IF category == current_category %]
87+
&lt;b&gt;[% category %]&lt;/b&gt;
88+
[% ELSE %]
89+
[% category %]
90+
[% END %]
91+
[% END %]
92+
93+
</pre>
94+
<p>Simple, and it provides excellent visual cues as to what the user is
95+
looking at.</p>
96+
<p>The problem with tags, though, is that an article can have lots of
97+
them. The technique above doesn't work there; you need to do a search
98+
for each tag. Not a show stopper, but do you really want to do array
99+
searches inside the Template Toolkit? No!</p>
100+
<p>And this is where <cite>Quantum::Superpositions</cite> comes to the rescue. In
101+
quantum physics, almost nothing is &quot;certain&quot; -- you can't tell with
102+
100% certainty both where a particle is and what its velocity is.
103+
The state of an individual particle is in sort of a flux until you
104+
observe, and when you observe, a tangible state comes into existence.</p>
105+
<p>How does this help with tags? By thinking of the set of all tags as a
106+
cloud of particles, we can apply the same principle. We don't care
107+
what all the tags are until we look at them.</p>
108+
<p>So how do we do this in perl? Let's see an example:</p>
109+
<p>In my
110+
<a href="http://www.jrock.us/trac/blog_software/browser/lib/Blog/Controller/Tags.pm#L96">Tags.pm</a>
111+
Controller, I use the <code>any</code> method from <code>Quantum::Superpositions</code> to
112+
collapse the list of tags into a scalar:</p>
113+
<pre> $c-&gt;stash-&gt;{article_tags} = any(@tags);
114+
115+
</pre>
116+
<p>Then inside my <a href="http://www.jrock.us/trac/blog_software/browser/root/navbox.tt#L40">Template Toolkit View</a>, I &quot;observe&quot; the state as
117+
necessary (with the <code>==</code> operator):</p>
118+
<pre> [% FOREACH tag = all_tags %]
119+
[% IF tag == article_tags %]
120+
&lt;b&gt;[% tag %]&lt;/b&gt;
121+
[% ELSE %]
122+
[% tag %]
123+
[% END %]
124+
[% END %]
125+
126+
</pre>
127+
<p>As you can see, this is exactly the same as what we did when we only
128+
had one possible value. If you think about it, it's really the same
129+
thing. You just needed to think more about physics :)</p>
130+
<p>Anyway, take a look at this in action:</p>
131+
<p><a href="http://blog.jrock.us/tags/%E3%83%A2%E3%83%BC%E5%A8%98%E3%80%82/music">http://blog.jrock.us/tags/%E3%83%A2%E3%83%BC%E5%A8%98%E3%80%82/music</a></p>
132+
<p>And then add some cool navigation features to your Catalyst app!
133+
</p>
134+
135+
136+
</div></div></content></entry></feed>

0 commit comments

Comments
 (0)