Skip Menu |

This queue is for tickets about the XML-RSS CPAN distribution.

Report information
The Basics
Id: 18817
Status: resolved
Priority: 0/
Queue: XML-RSS

People
Owner: Nobody in particular
Requestors: ryantate [...] ryantate.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.10
Fixed in: (no value)



Subject: RSS 2.0 spec allows omission of title from entry
The spec for RSS 2.0 allows entries without titles, provided they have descriptions. However, XML::RSS ignores any entries without titles when rendering via ->as_string for RSS2 (internally via ->as_rss_2_0). From RSS spec, http://blogs.law.harvard.edu/tech/rss "All elements of an item are optional, however at least one of title or description must be present." -Ryan Tate ryantate@ryantate.com
From: SHLOMIF [...] cpan.org
On Fri Apr 21 11:24:36 2006, guest wrote: Show quoted text
> The spec for RSS 2.0 allows entries without titles, provided they
have Show quoted text
> descriptions. However, XML::RSS ignores any entries without titles
when Show quoted text
> rendering via ->as_string for RSS2 (internally via ->as_rss_2_0). > > From RSS spec, http://blogs.law.harvard.edu/tech/rss > > "All elements of an item are optional, however at least one of title
or Show quoted text
> description must be present." >
Granted. The attached patch fixes this problem. ABH, please apply it to the master repository. Regards, Shlomi Fish Show quoted text
> -Ryan Tate > ryantate@ryantate.com > >
=== t/2.0-wo-title.t ================================================================== --- t/2.0-wo-title.t (revision 331) +++ t/2.0-wo-title.t (revision 333) @@ -0,0 +1,45 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More tests => 2; + +# TEST +use_ok('XML::RSS'); + +my $rss = XML::RSS->new(version => '2.0'); + +$rss->channel( + title => 'freshmeat.net', + 'link' => 'http://freshmeat.net', + language => 'en', + description => 'the one-stop-shop for all your Linux software needs', + rating => '(PICS-1.1 "http://www.classify.org/safesurf/" 1 r (SS~~000 1))', + copyright => 'Copyright 1999, Freshmeat.net', + pubDate => 'Thu, 23 Aug 1999 07:00:00 GMT', + lastBuildDate => 'Thu, 23 Aug 1999 16:20:26 GMT', + docs => 'http://www.blahblah.org/fm.cdf', + managingEditor => 'scoop@freshmeat.net', + webMaster => 'scoop@freshmeat.net' + ); + +$rss->add_item( + # creates a guid field with permaLink=true + permaLink => "http://freshmeat.net/news/1999/06/21/930003829.html", + # alternately creates a guid field with permaLink=false + # guid => "gtkeyboard-0.85 + enclosure => { url=>"http://www.foo.tld/", type=>"application/x-bittorrent" }, + description => 'My Life Changed Absolutely', +); + +my $string = $rss->as_string(); + +# TEST +ok ( + (index($string, + '<description>My Life Changed Absolutely</description>' + ) >= 0 + ), + "Testing for the item being rendered." +); + +1; === t/test_manifest ================================================================== --- t/test_manifest (revision 331) +++ t/test_manifest (revision 333) @@ -8,6 +8,7 @@ 2.0-parse.t 2.0-generate.t 2.0-permalink.t +2.0-wo-title.t encode-output.t auto_add_modules.t rss2-gt-encoding.t === MANIFEST ================================================================== --- MANIFEST (revision 331) +++ MANIFEST (revision 333) @@ -39,6 +39,7 @@ t/2.0-generate.t t/2.0-parse.t t/2.0-permalink.t +t/2.0-wo-title.t t/auto_add_modules.t t/encode-output.t t/encoding.t === lib/XML/RSS.pm ================================================================== --- lib/XML/RSS.pm (revision 331) +++ lib/XML/RSS.pm (revision 333) @@ -1241,53 +1241,57 @@ ################ # item element # ################ + ITEMS_LOOP: foreach my $item (@{$self->{items}}) { - if ($item->{title}) { - $output .= '<item>'."\n"; - $output .= '<title>'.$self->encode($item->{title}).'</title>'."\n" - if $item->{title}; - $output .= '<link>'.$self->encode($item->{'link'}).'</link>'."\n" - if $item->{link}; - $output .= '<description>'.$self->encode($item->{description}).'</description>'."\n" - if $item->{description}; + # According to the spec either title or description must be present. + if (!(exists($item->{title}) || exists($item->{description}))) + { + next ITEMS_LOOP; + } + $output .= '<item>'."\n"; + $output .= '<title>'.$self->encode($item->{title}).'</title>'."\n" + if $item->{title}; + $output .= '<link>'.$self->encode($item->{'link'}).'</link>'."\n" + if $item->{link}; + $output .= '<description>'.$self->encode($item->{description}).'</description>'."\n" + if $item->{description}; - $output .= '<author>'.$self->encode($item->{author}).'</author>'."\n" - if $item->{author}; + $output .= '<author>'.$self->encode($item->{author}).'</author>'."\n" + if $item->{author}; - $output .= '<category>'.$self->encode($item->{category}).'</category>'."\n" - if $item->{category}; + $output .= '<category>'.$self->encode($item->{category}).'</category>'."\n" + if $item->{category}; - $output .= '<comments>'.$self->encode($item->{comments}).'</comments>'."\n" - if $item->{comments}; + $output .= '<comments>'.$self->encode($item->{comments}).'</comments>'."\n" + if $item->{comments}; - # The unique identifier. Use 'permaLink' for an external - # identifier, or 'guid' for a internal string. - # (I call it permaLink in the hash for purposes of clarity.) - if ($item->{permaLink}) - { - $output .= '<guid isPermaLink="true">'.$self->encode($item->{permaLink}).'</guid>'."\n"; - } - elsif ($item->{guid}) - { - $output .= '<guid isPermaLink="false">'.$self->encode($item->{guid}).'</guid>'."\n"; - } + # The unique identifier. Use 'permaLink' for an external + # identifier, or 'guid' for a internal string. + # (I call it permaLink in the hash for purposes of clarity.) + if ($item->{permaLink}) + { + $output .= '<guid isPermaLink="true">'.$self->encode($item->{permaLink}).'</guid>'."\n"; + } + elsif ($item->{guid}) + { + $output .= '<guid isPermaLink="false">'.$self->encode($item->{guid}).'</guid>'."\n"; + } - $output .= '<pubDate>'.$self->encode($item->{pubDate}).'</pubDate>'."\n" - if $item->{pubDate}; + $output .= '<pubDate>'.$self->encode($item->{pubDate}).'</pubDate>'."\n" + if $item->{pubDate}; - $output .= '<source url="'.$self->encode($item->{sourceUrl}).'">'.$item->{source}.'</source>'."\n" - if $item->{source} && $item->{sourceUrl}; + $output .= '<source url="'.$self->encode($item->{sourceUrl}).'">'.$item->{source}.'</source>'."\n" + if $item->{source} && $item->{sourceUrl}; - if (my $e = $item->{enclosure}) - { - $output .= "<enclosure " - . join(' ', map {qq!$_="! . $self->encode($e->{$_}) . qq!"!} keys(%$e)) - . ' />' . "\n"; - } + if (my $e = $item->{enclosure}) + { + $output .= "<enclosure " + . join(' ', map {qq!$_="! . $self->encode($e->{$_}) . qq!"!} keys(%$e)) + . ' />' . "\n"; + } - # end image element - $output .= '</item>'."\n\n"; - } + # end image element + $output .= '</item>'."\n\n"; } #####################
Show quoted text
> > Granted. The attached patch fixes this problem. ABH, please apply it > to the master repository.
Eek, can you recreate the patch with diff -uw to omit the whitespace changes? (It doesn't apply automatically and the whitespace changes makes it hard to do by hand).
On Tue Oct 24 14:36:26 2006, ABH wrote: Show quoted text
>
> > > > Granted. The attached patch fixes this
problem. ABH, please apply it Show quoted text
> > to the master repository.
> > Eek, can you recreate the patch with diff -uw to
omit the whitespace Show quoted text
> changes? (It doesn't apply > automatically and the whitespace changes makes
it hard to do by hand). OK, I will. Regards, Shlomi Fish
On Tue Oct 24 14:36:26 2006, ABH wrote: Show quoted text
>
> > > > Granted. The attached patch fixes this problem. ABH, please apply
it Show quoted text
> > to the master repository.
> > Eek, can you recreate the patch with diff -uw to omit the whitespace > changes? (It doesn't apply > automatically and the whitespace changes makes it hard to do by
hand). Attached. The reason I have different whitespace is because I decreased the indentation after converting for { if ($cond) { [BODY] } to for { if (!$cond){ next;} [BODY] }.
--- t/2.0-wo-title.t (revision 331) +++ t/2.0-wo-title.t (revision 332) @@ -0,0 +1,45 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More tests => 2; + +# TEST +use_ok('XML::RSS'); + +my $rss = XML::RSS->new(version => '2.0'); + +$rss->channel( + title => 'freshmeat.net', + 'link' => 'http://freshmeat.net', + language => 'en', + description => 'the one-stop-shop for all your Linux software needs', + rating => '(PICS-1.1 "http://www.classify.org/safesurf/" 1 r (SS~~000 1))', + copyright => 'Copyright 1999, Freshmeat.net', + pubDate => 'Thu, 23 Aug 1999 07:00:00 GMT', + lastBuildDate => 'Thu, 23 Aug 1999 16:20:26 GMT', + docs => 'http://www.blahblah.org/fm.cdf', + managingEditor => 'scoop@freshmeat.net', + webMaster => 'scoop@freshmeat.net' + ); + +$rss->add_item( + # creates a guid field with permaLink=true + permaLink => "http://freshmeat.net/news/1999/06/21/930003829.html", + # alternately creates a guid field with permaLink=false + # guid => "gtkeyboard-0.85 + enclosure => { url=>"http://www.foo.tld/", type=>"application/x-bittorrent" }, + description => 'My Life Changed Absolutely', +); + +my $string = $rss->as_string(); + +# TEST +ok ( + (index($string, + '<description>My Life Changed Absolutely</description>' + ) >= 0 + ), + "Testing for the item being rendered." +); + +1; --- t/test_manifest (revision 331) +++ t/test_manifest (revision 332) @@ -8,6 +8,7 @@ 2.0-parse.t 2.0-generate.t 2.0-permalink.t +2.0-wo-title.t encode-output.t auto_add_modules.t rss2-gt-encoding.t --- MANIFEST (revision 331) +++ MANIFEST (revision 332) @@ -39,6 +39,7 @@ t/2.0-generate.t t/2.0-parse.t t/2.0-permalink.t +t/2.0-wo-title.t t/auto_add_modules.t t/encode-output.t t/encoding.t --- lib/XML/RSS.pm (revision 331) +++ lib/XML/RSS.pm (revision 332) @@ -1241,8 +1241,13 @@ ################ # item element # ################ + ITEMS_LOOP: foreach my $item (@{$self->{items}}) { - if ($item->{title}) { + # According to the spec either title or description must be present. + if (!(exists($item->{title}) || exists($item->{description}))) + { + next ITEMS_LOOP; + } $output .= '<item>'."\n"; $output .= '<title>'.$self->encode($item->{title}).'</title>'."\n" if $item->{title}; @@ -1288,7 +1293,6 @@ # end image element $output .= '</item>'."\n\n"; } - } ##################### # textinput element #
I added Shlomi's test to SVN and made a fix, thanks!