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