Subject: | POE-Filter-XML doesn't play nice with other XML code |
Initial problem report here: http://www.perlmonks.org/?node_id=603660
The basic problem is that XML::SAX::Expat::Incremental does not
implement the full SAX API (specifically, it can only parse from a
string and not from a file). This is the reason that
XML::SAX::Expat::Incremental does not register itself in
XML/SAX/ParserDetails.ini (see:
https://rt.cpan.org/Public/Bug/Display.html?id=13764 ).
POE::Filter::XML needs to use XML::SAX::Expat::Incremental and it
achieves this by setting the $XML::SAX::ParserPackage global.
Unfortunately that global setting means that any other code in the same
script that wants a SAX parser will also get a
XML::SAX::Expat::Incremental parser object. That other code won't work
if it tries to use a part of the SAX API that the incremental parser
doesn't implement, such as parsing from a file.
One solution would be for POE::Filter::XML to localise the
$XML::SAX::ParserPackage global assignment to the block of code that
needs it.
A simpler solution would be not to use XML::SAX::ParserFactory at all.
The point of the factory is to allow a program to get a SAX parser
without having to know which modules are installed. That circumstance
doesn't apply to POE::Filter::XML since it only works with one parser.
So there's no harm in it instantiating a XML::SAX::Expat::Incremental
parser directly as per the attached patch. Using the factory just adds
an unnecessary layer of indirection.
The XML::SAX::Expat::Incremental documentation warns that you shouldn't
do that and you should always use the ParserFactory - that's a mistake.
It's perfectly reasonable to instantiate a specific parser if your code
only works with that parser.
Subject: | sax-incremental.patch |
--- lib/POE/Filter/XML.pm 2007-01-20 20:09:00.000000000 +1300
+++ lib/POE/Filter/XML.pm 2007-03-10 16:04:03.000000000 +1300
@@ -5,11 +5,10 @@
our $VERSION = '0.33';
use XML::SAX;
-use XML::SAX::ParserFactory;
+use XML::SAX::Expat::Incremental;
use POE::Filter::XML::Handler;
use Scalar::Util qw/weaken/;
use Carp;
-$XML::SAX::ParserPackage = "XML::SAX::Expat::Incremental";
# This is to make Filter::Stackable happy
use base('POE::Filter');
@@ -46,7 +45,7 @@
$handler = POE::Filter::XML::Handler->new();
}
- my $parser = XML::SAX::ParserFactory->parser('Handler' => $handler);
+ my $parser = XML::SAX::Expat::Incremental->new('Handler' => $handler);
$self->{'handler'} = $handler;
$self->{'parser'} = $parser;