Skip Menu |

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

Report information
The Basics
Id: 11569
Status: resolved
Worked: 3 min
Priority: 0/
Queue: XML-RSS

People
Owner: SHLOMIF [...] cpan.org
Requestors: smithj4 [...] bnl.gov
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.05
Fixed in: (no value)



Subject: Quick patch to allow inserting a XSL stylesheet URL into the XML output.
I wanted to have the RSS XML produced by this module be able to include an optional XSL stylesheet URL, so I made this quick patch that adds a stylesheet option. ~Jason
diff -uNr XML-RSS-1.05-dist/lib/RSS.pm XML-RSS-1.05/lib/RSS.pm --- XML-RSS-1.05-dist/lib/RSS.pm 2004-04-21 03:14:43.000000000 -0400 +++ XML-RSS-1.05/lib/RSS.pm 2005-02-18 10:32:35.000000000 -0500 @@ -473,6 +473,11 @@ ? ($self->{encoding} = $hash{encoding}) : ($self->{encoding} = 'UTF-8'); + # set default stylesheet + (exists($hash{stylesheet})) + ? ($self->{stylesheet} = $hash{stylesheet}) + : ($self->{stylesheet} = ""); + # initialize RSS data structure # RSS version 0.9 if ($self->{version} eq '0.9') { @@ -562,7 +567,9 @@ # XML declaration my $encoding = exists $$self{encoding} ? qq| encoding="$$self{encoding}"| : ''; - $output .= qq|<?xml version="1.0"$encoding?>\n\n|; + $output .= qq|<?xml version="1.0"$encoding?>\n|; + $output .= '<?xml-stylesheet type="text/xsl" href="'.$self->{stylesheet}.'"?>'."\n" if $self->{stylesheet}; + $output .= "\n"; # RDF root element $output .= '<rdf:RDF'."\n".'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'."\n"; @@ -633,7 +640,9 @@ my $output; # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; + $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n"; + $output .= '<?xml-stylesheet type="text/xsl" href="'.$self->{stylesheet}.'"?>'."\n" if $self->{stylesheet}; + $output .= "\n"; # DOCTYPE $output .= '<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"'."\n"; @@ -793,7 +802,9 @@ my $output; # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; + $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n"; + $output .= '<?xml-stylesheet type="text/xsl" href="'.$self->{stylesheet}.'"?>'."\n" if $self->{stylesheet}; + $output .= "\n"; # RDF namespaces declaration $output .="<rdf:RDF"."\n"; @@ -1066,7 +1077,9 @@ my $output; # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; + $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n"; + $output .= '<?xml-stylesheet type="text/xsl" href="'.$self->{stylesheet}.'"?>'."\n" if $self->{stylesheet}; + $output .= "\n"; # DOCTYPE # $output .= '<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"'."\n"; @@ -2002,7 +2015,7 @@ =over 4 =item new XML::RSS (version=>$version, encoding=>$encoding, -output=>$output) +output=>$output, stylesheet=>$stylesheet_url) Constructor for XML::RSS. It returns a reference to an XML::RSS object. You may also pass the RSS version and the XML encoding to use. The default @@ -2011,6 +2024,9 @@ when you want to convert RSS between versions. The XML::RSS modules will convert between any of the formats. If you set <encode_output> XML::RSS will make sure to encode any entities in generated RSS. This is now on by default. +You can also specify an optional URL to a XSL stylesheet to be added to the XML +output. This will allow most web browsers to render the RSS XML document as if +it were an HTML document. =item add_item (title=>$title, link=>$link, description=>$desc, mode=>$mode)
From: SHLOMIF [...] cpan.org
On Fri Feb 18 12:00:50 2005, guest wrote: Show quoted text
> I wanted to have the RSS XML produced by this module be able to > include an optional XSL stylesheet URL, so I made this quick patch > that adds a stylesheet option. > > ~Jason
Here's a reworked version of this patch that: 1. Adds a test suite with regression tests. 2. Adds encode to the stylesheet URL. 3. Extracts duplicate code into a method. ABH, please apply it. Regards, Shlomi Fish
=== t/xml-header.t ================================================================== --- t/xml-header.t (revision 445) +++ t/xml-header.t (revision 448) @@ -0,0 +1,176 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 8; + +use XML::RSS; + +sub starts_with +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + my ($rss, $prefix, $msg) = @_; + my $rss_output = $rss->as_string(); + my $ok = is ( + substr($rss_output, 0, length($prefix)), + $prefix, + $msg + ); +} + +sub create_rss_1 +{ + my $args = shift; + # my $rss = new XML::RSS (version => '0.9'); + my @style = + exists($args->{stylesheet}) ? + (stylesheet => $args->{stylesheet}) : + () + ; + my $rss = XML::RSS->new( + version => $args->{version}, + @style + ); + my $image_link = exists($args->{image_link}) ? $args->{image_link} : + "http://freshmeat.net/"; + + my $extra_image_params = $args->{image_params} || []; + + $rss->channel( + title => "freshmeat.net", + link => "http://freshmeat.net", + description => "the one-stop-shop for all your Linux software needs", + ); + + $rss->image( + title => "freshmeat.net", + url => "0", + link => $image_link, + @{$extra_image_params}, + ); + + $rss->add_item( + title => "GTKeyboard 0.85", + link => "http://freshmeat.net/news/1999/06/21/930003829.html" + ); + + return $rss; +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "0.9"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> + +<rdf:RDF +EOF + "header of RSS 0.9 without the stylesheet" + ); +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "0.91"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" + "http://my.netscape.com/publish/formats/rss-0.91.dtd"> + +<rss version="0.91"> +EOF + "header of RSS 0.9.1 without the stylesheet" + ); +} + + +{ + # TEST + starts_with( + create_rss_1({'version' => "1.0"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> + +<rdf:RDF +EOF + "header of RSS 1.0 without the stylesheet" + ); +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "2.0"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> + +<rss + version="2.0" +EOF + "header of RSS 2.0 without the stylesheet" + ); +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "0.9", stylesheet => "http://myhost.tld/foo.xsl"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> +<?xml-stylesheet type="text/xsl" href="http://myhost.tld/foo.xsl"?> + +<rdf:RDF +EOF + "header of RSS 0.9 with the stylesheet" + ); +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "0.91", stylesheet => "http://myhost.tld/foo.xsl"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> +<?xml-stylesheet type="text/xsl" href="http://myhost.tld/foo.xsl"?> + +<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" + "http://my.netscape.com/publish/formats/rss-0.91.dtd"> + +<rss version="0.91"> +EOF + "header of RSS 0.9.1 with the stylesheet" + ); +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "1.0", stylesheet => "http://myhost.tld/foo.xsl"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> +<?xml-stylesheet type="text/xsl" href="http://myhost.tld/foo.xsl"?> + +<rdf:RDF +EOF + "header of RSS 1.0 without the stylesheet" + ); +} + +{ + # TEST + starts_with( + create_rss_1({'version' => "2.0", stylesheet => "http://myhost.tld/foo.xsl"}), + <<'EOF', +<?xml version="1.0" encoding="UTF-8"?> +<?xml-stylesheet type="text/xsl" href="http://myhost.tld/foo.xsl"?> + +<rss + version="2.0" +EOF + "header of RSS 2.0 without the stylesheet" + ); +} === t/test_manifest ================================================================== --- t/test_manifest (revision 445) +++ t/test_manifest (revision 448) @@ -24,3 +24,4 @@ #pod-coverage.t rss2-gt-encoding.t charset1.t +xml-header.t === MANIFEST ================================================================== --- MANIFEST (revision 445) +++ MANIFEST (revision 448) @@ -53,4 +53,5 @@ t/rss2-gt-encoding.t t/test_manifest t/version.t +t/xml-header.t TODO === lib/XML/RSS.pm ================================================================== --- lib/XML/RSS.pm (revision 445) +++ lib/XML/RSS.pm (revision 448) @@ -496,6 +496,12 @@ ? ($self->{encoding} = $hash{encoding}) : ($self->{encoding} = 'UTF-8'); + # stylesheet + if (exists($hash{stylesheet})) + { + $self->{stylesheet} = $hash{stylesheet}; + } + # initialize RSS data structure # RSS version 0.9 if ($self->{version} eq '0.9') { @@ -740,15 +746,29 @@ } } +sub _output_xml_declaration +{ + my $self = shift; + + $self->_out('<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n"); + if (defined($self->{stylesheet})) + { + my $style_url = $self->_encode($self->{stylesheet}); + $self->_out(qq{<?xml-stylesheet type="text/xsl" href="$style_url"?>\n}); + } + + $self->_out("\n"); + + return undef; +} + sub as_rss_0_9 { my $self = shift; my $output; $self->_set_output_var(\$output); - # XML declaration - my $encoding = exists $$self{encoding} ? qq| encoding="$$self{encoding}"| : ''; - $output .= qq|<?xml version="1.0"$encoding?>\n\n|; + $self->_output_xml_declaration(); # RDF root element $output .= '<rdf:RDF'."\n".'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'."\n"; @@ -869,9 +889,9 @@ my $output; $self->_set_output_var(\$output); - # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; + $self->_output_xml_declaration(); + # DOCTYPE $output .= '<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"'."\n"; $output .= ' "http://my.netscape.com/publish/formats/rss-0.91.dtd">'."\n\n"; @@ -996,8 +1016,7 @@ $self->_set_output_var(\$output); - # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; + $self->_output_xml_declaration(); # RDF namespaces declaration $output .="<rdf:RDF"."\n"; @@ -1278,9 +1297,9 @@ my $output; $self->_set_output_var(\$output); - # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; + $self->_output_xml_declaration(); + # DOCTYPE # $output .= '<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"'."\n"; # $output .= ' "http://my.netscape.com/publish/formats/rss-0.91.dtd">'."\n\n"; @@ -2126,7 +2145,7 @@ =over 4 =item new XML::RSS (version=>$version, encoding=>$encoding, -output=>$output) +output=>$output, stylesheet=>$stylesheet_url) Constructor for XML::RSS. It returns a reference to an XML::RSS object. You may also pass the RSS version and the XML encoding to use. The default @@ -2134,8 +2153,13 @@ the B<output> format regarless of the input version. This comes in handy when you want to convert RSS between versions. The XML::RSS modules will convert between any of the formats. If you set <encode_output> XML::RSS -will make sure to encode any entities in generated RSS. This is now on by default. +will make sure to encode any entities in generated RSS. This is now on by +default. +You can also pass an optional URL to an XSL stylesheet that can be used to +output an C<<< <?xsl-stylesheet ... ?> >>> meta-tag in the header that will +allow some browsers to render the RSS file as HTML. + =item add_item (title=>$title, link=>$link, description=>$desc, mode=>$mode) Adds an item to the XML::RSS object. B<mode> and B<description> are optional.
Done for 1.21, thanks!
Subject: Re: [rt.cpan.org #11569] Quick patch to allow inserting a XSL stylesheet URL into the XML output.
Date: Wed, 20 Dec 2006 17:54:32 -0500
To: bug-XML-RSS [...] rt.cpan.org
From: "Jason A. Smith" <smithj4 [...] bnl.gov>
Hi, In case you want to revisit this issue, I just learned that Firefox >= 2 and IE >= 7 now ignore the publisher's stylesheet in favor of the web browser's own builtin stylesheet for RSS XML documents, see: https://bugzilla.mozilla.org/show_bug.cgi?id=338621 Apparently the mozilla developers feel this behavior is correct and are unwilling to fix it since it gives the user a uniform experience. Obviously this completely breaks the XML::RSS stylesheet option unless a large comment is added before the document type declaration like is suggested in the above bug report. Therefore I have created another patch against version 1.22 to do just this, see attachment. ~Jason On Tue, 2006-11-28 at 20:22 -0500, via RT wrote: Show quoted text
> <URL: http://rt.cpan.org/Ticket/Display.html?id=11569 > > > Done for 1.21, thanks! >
-- /------------------------------------------------------------------\ | Jason A. Smith Email: smithj4@bnl.gov | | Atlas Computing Facility, Bldg. 510M Phone: +1-631-344-4226 | | Brookhaven National Lab, P.O. Box 5000 Fax: +1-631-344-7616 | | Upton, NY 11973-5000, U.S.A. | \------------------------------------------------------------------/
diff -uNr XML-RSS-1.22-dist/lib/XML/RSS.pm XML-RSS-1.22/lib/XML/RSS.pm --- XML-RSS-1.22-dist/lib/XML/RSS.pm 2006-12-17 09:18:25.663925658 -0500 +++ XML-RSS-1.22/lib/XML/RSS.pm 2006-12-19 18:18:47.052599941 -0500 @@ -862,6 +862,15 @@ { my $style_url = $self->_encode($self->{stylesheet}); $self->_out(qq{<?xml-stylesheet type="text/xsl" href="$style_url"?>\n}); + $self->_out(qq{<!-- Apparently, Mozilla Firefox >= 2 & IE >= 7 have decided that they know + better and will ignore the publisher's own stylesheet in favor of the web + browser's builtin stylesheet for certain types of xml documents, see: + https://bugzilla.mozilla.org/show_bug.cgi?id=338621. Since they seem to + be refusing to fix this obvious bug, they are forcing the web publishers + to add bogus comments before the document type declaration so the browser, + which only sniffs the first 512 bytes of the document, will not see the + document type declaration and decide to use its own builtin stylesheet, + hence this long comment! -->}); } $self->_out("\n");
On Wed Dec 20 17:55:08 2006, smithj4@bnl.gov wrote: Show quoted text
> Hi, > > In case you want to revisit this issue, I just learned that Firefox >= 2 > and IE >= 7 now ignore the publisher's stylesheet in favor of the web > browser's own builtin stylesheet for RSS XML documents, see: > > https://bugzilla.mozilla.org/show_bug.cgi?id=338621 > > Apparently the mozilla developers feel this behavior is correct and
are Show quoted text
> unwilling to fix it since it gives the user a uniform experience. > Obviously this completely breaks the XML::RSS stylesheet option
unless a Show quoted text
> large comment is added before the document type declaration like is > suggested in the above bug report. Therefore I have created another > patch against version 1.22 to do just this, see attachment. > > ~Jason >
Hi Jason! I am reluctant to incorporate this patch for several reasons: 1. It is a workaround for a mis-behaviour of certain browsers. And Real programmers don't write workarounds - they expect users to upgrade their software. 2. It will un-necessarily bloat the markup. Many users of the module probably expect it to generate markup with a size as small as possible, so they can reduce their bandwidth. 3. We may keep it lying around after these limitations have been lifted. 4. It doesn't affect all the possible uses of RSS. 5. You can already do it with relative ease using the svn trunk (which your patch is incompatible with). To do so: 4.1. Subclass XML::RSS::Private::Output::V2_0. If you want a different RSS version then subclass a different class. 4.2 In the subclass, write the following code: <<<<<<<<<<< sub _output_xml_declaration { my $self = shift; $self->SUPER::_output_xml_declaration(); $self->_out(qq{Blah blah blah}); } Show quoted text
>>>>>>>>>>>
4.3. Subclass XML::RSS. 4.4. Im the subclass, rwite the following code: <<<<<<<<<<<<< sub _get_rendering_class { return "Path::To::My::V2_0::Subclass"; } Show quoted text
>>>>>>>>>>>>>
4.5. Use the XML::RSS subclass normally. I didn't test this code, so it may require some tweaking to compile. But it's a solved problem. Regards, Shlomi Fish Show quoted text
> > On Tue, 2006-11-28 at 20:22 -0500, via RT wrote:
> > <URL: http://rt.cpan.org/Ticket/Display.html?id=11569 > > > > > Done for 1.21, thanks! > >
Like I said in my comment, one can do it already by sub-classing, so I'm closing this. Regards, Shlomi Fish