Skip Menu |

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

Report information
The Basics
Id: 68726
Status: resolved
Priority: 0/
Queue: XML-Writer

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

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



Subject: Correct minor bug to properly support OUTPUT ducktyping
Compare these two blocks: { my $out = bless [], 'DuckOutput'; my $x = XML::Writer->new( OUTPUT=>$out, ); $x->xmlDecl('utf-8'); } { my $out = bless [], 'DuckOutput'; my $x = XML::Writer->new( OUTPUT=>$out, ENCODING=>'utf-8', ); $x->xmlDecl(); } The first one will work with the code in 0.612, the second seemingly similar code will execute a codepath that attempts to run binmode($out), which dies with "Not a GLOB reference". DuckOutput is just a hypothetical class that has a print() method. XML::Writer *Almost* supports "Duck Typing" for the OUTPUT parameter, and in fact, includes it's own inline package with a 'print' method for the case where someone passes in a scalar reference. This patch adds documentation, test cases, and a minor code patch to support passing in any arbitrary object that has a print() method. Taking an cue from Plack's recommendations, I'm purposely not checking if the object has a print() method defined. It is in fact possible to pull off duck-typing *without* this patch by exploiting this unintended (undocumented?) codepath. I'm hoping with the addition of this patch, it can become 'officially' supported so the technique doesn't vanish in the future. I've tested this patch against perl 5.14.0 on linux/x86. Thanks for supporting a very useful module.
Subject: Ducktyping.diff
diff -ur XML-Writer-0.612/t/01_main.t XML-Writer-0.612-jason//t/01_main.t --- XML-Writer-0.612/t/01_main.t 2010-08-15 10:11:12.000000000 -0400 +++ XML-Writer-0.612-jason//t/01_main.t 2011-06-10 00:08:34.000000000 -0400 @@ -15,9 +15,13 @@ use Errno; -use Test::More(tests => 236); +use Test::More(tests => 238); +use Encode; +# part of the Duck-Typing Output test. +our $duckoutput; + # Catch warnings my $warning; @@ -1974,12 +1978,74 @@ is($w->getDataIndent(), 0, 'Non-numeric indent should fall back to zero'); }; + +TEST: { + my $output = bless [],'DuckOutput'; + initEnv( + OUTPUT=>$output, + ENCODING=>'UTF-8' + ); + $w->xmlDecl(); + + is($duckoutput,qq{<?xml version="1.0" encoding="UTF-8"?>\n},"Basic Duck Typing output"); +}; + +SKIP: { + skip $unicodeSkipMessage, 1 unless isUnicodeSupported(); + $duckoutput= ''; + my $output = bless [],'DuckOutput'; + initEnv( + OUTPUT=>$output, + ENCODING=>'utf-8', + DATA_MODE=>1, + ); + + $w->xmlDecl(); + $w->comment("\$ \x{A3} \x{20AC}"); + $w->startTag('a'); + $w->dataElement('b', '$'); + + # I need U+00A3 as an is_utf8 string; I want to keep the source ASCII. + # There must be a better way to do this. + require Encode; + my $text = Encode::decode('iso-8859-1', "\x{A3}"); + $w->dataElement('b', $text); + + $w->dataElement('b', "\x{20AC}"); + $w->startTag('c'); + $w->cdata(" \$ \x{A3} \x{20AC} "); + $w->endTag('c'); + $w->endTag('a'); + $w->end(); + + is($duckoutput,decode('utf-8',<<EOR), 'When requested, output should be UTF-8 encoded, when using Duck Type output'); +<?xml version="1.0" encoding="utf-8"?> +<!-- \$ \x{C2}\x{A3} \x{E2}\x{82}\x{AC} --> + +<a> +<b>\x{24}</b> +<b>\x{C2}\x{A3}</b> +<b>\x{E2}\x{82}\x{AC}</b> +<c><![CDATA[ \$ \x{C2}\x{A3} \x{E2}\x{82}\x{AC} ]]></c> +</a> +EOR + + +} + + + # Free test resources $outputFile->close() or die "Unable to close temporary file: $!"; 1; +package DuckOutput; + +sub print { shift; $duckoutput.=join('', @_); } + + package XML::Writer::Test::FailingWriter; sub new diff -ur XML-Writer-0.612/Writer.pm XML-Writer-0.612-jason//Writer.pm --- XML-Writer-0.612/Writer.pm 2010-08-15 10:11:12.000000000 -0400 +++ XML-Writer-0.612-jason//Writer.pm 2011-06-10 00:10:44.000000000 -0400 @@ -470,7 +470,7 @@ # If there is no OUTPUT parameter, # use standard output $output = $newOutput || \*STDOUT; - if ($outputEncoding) { + if ($outputEncoding && ref($output) && $output->isa('IO::Handle') ) { if (lc($outputEncoding) eq 'utf-8') { binmode($output, ':encoding(utf-8)'); } elsif (lc($outputEncoding) eq 'us-ascii') { @@ -1249,11 +1249,11 @@ =item OUTPUT -An object blessed into IO::Handle or one of its subclasses (such as -IO::File), or a reference to a string; if this parameter is not present, -the module will write to standard output. If a string reference is passed, -it will capture the generated XML (as a string; to get bytes use the -C<Encode> module). +An object blessed into IO::Handle or one of its subclasses (such as IO::File), +or a reference to a string, or any blessed object that has a print() method; +if this parameter is not present, the module will write to standard output. If +a string reference is passed, it will capture the generated XML (as a string; +to get bytes use the C<Encode> module). =item NAMESPACES
Thanks, nice fix. Thanks for the tests and documentation!