XML-SAX-Expat-Incremental-0.05/0000755000076500007650000000000010673655336020765 5ustar nothingmuchnothingmuch00000000000000XML-SAX-Expat-Incremental-0.05/Changes0000644000076500007650000000014310673655122022247 0ustar nothingmuchnothingmuch000000000000000.05 - Fix a leak (http://rt.cpan.org/Public/Bug/Display.html?id=23838), thanks to Nicholas Perez XML-SAX-Expat-Incremental-0.05/lib/0000755000076500007650000000000010673655333021530 5ustar nothingmuchnothingmuch00000000000000XML-SAX-Expat-Incremental-0.05/lib/XML/0000755000076500007650000000000010673655333022170 5ustar nothingmuchnothingmuch00000000000000XML-SAX-Expat-Incremental-0.05/lib/XML/SAX/0000755000076500007650000000000010673655333022623 5ustar nothingmuchnothingmuch00000000000000XML-SAX-Expat-Incremental-0.05/lib/XML/SAX/Expat/0000755000076500007650000000000010673655333023704 5ustar nothingmuchnothingmuch00000000000000XML-SAX-Expat-Incremental-0.05/lib/XML/SAX/Expat/Incremental.pm0000644000076500007650000001216210673655241026503 0ustar nothingmuchnothingmuch00000000000000#!/usr/bin/perl -w package XML::SAX::Expat::Incremental; use base qw/XML::SAX::Expat/; use strict; #use warnings; use vars qw/$VERSION/; $VERSION = "0.05"; use XML::Parser (); use Carp qw/croak/; use Scalar::Util qw/weaken/; sub parse { my $p = shift; my $opts = $p->get_options(@_); if ($p->{Parent}){ return $p->{Parent}->parse($opts); } else { if (defined $opts->{Source}{String}){ return $p->_parse_string($opts->{Source}{String}); } else { croak "The only thing I know how to parse is a string. You have to fetch the data for me yourself."; } } } sub parse_more { my $p = shift; $p->parse_string(@_); } sub _parse_string { my $p = shift; my $xml = shift; $p->parse_start unless $p->{_parsing}; $p->_expat_obj->parse_more($xml); } sub parse_start { my $p = shift; my $opt = shift; croak "Can't parse_start - Already started" if $p->{_parsing}; $p->{_parsing} = 1; $p->_really_create_parser($opt); $p->_expat_obj($p->_parser_obj->parse_start); } sub parse_done { my $p = shift; croak "Can't parse_done - Havn't started parsing. Call parse_start or just parse first." unless $p->{_parsing}; undef $p->{_parsing}; $p->_expat_obj->parse_done; } sub _really_create_parser { # we only create the parser when parse_start is called my $p = shift; my $opt = shift; $p->{_xml_parser_obj} ||= $p->SUPER::_create_parser($opt); } sub _create_parser { # this is defined by XML::SAX::Expat my $p = shift; $p->_expat_obj; } sub _expat_obj { my $p = shift; $p->{_expat_nb_obj} = shift if @_; weaken($p->{_expat_nb_obj}); $p->{_expat_nb_obj}; } sub _parser_obj { my $p = shift; $p->{_xml_parser_obj} = shift if @_; weaken($p->{_xml_parser_obj}{__XSE}); # FIXME should go away $p->{_xml_parser_obj}; } __PACKAGE__ __END__ =pod =head1 NAME XML::SAX::Expat::Incremental - XML::SAX::Expat subclass for non-blocking (incremental) parsing, with L. =head1 SYNOPSIS use XML::SAX::Expat::Incremental; # don't do this, use XML::SAX::ParserFactory my $p = XML::SAX::Expat::Incremental->new( Handler => MyHandler->new ); $p->parse_start; while (){ $p->parse_more($_); # or $p->parse_string($_); } $p->parse_done; =head1 DESCRIPTION Most XML parsers give a callback interface within an encapsulated loop. That is, you call $p->parse_whatever($whatever); And eventually, when C<$whatever> is depleted by the parser, C<< $p->parse >> will return. Sometimes you don't want the parser to control the loop for you. For example, if you need to retrieve your XML in chunks in a funny way, you might need to do something like my $doc = ''; while (defined(my $buffer = get_more_xml())) { $doc .= $buffer; } $p->parse_string($doc); which is not very convenient, or efficient. You could use L to tie a filehandle which does this for you, but that only works some of the time (for example, say you have two inputs coming in simultaneously). L solves this by providing three methods: =over 4 =item parse_start =item parse_more =item parse_done =back This interface lets you move the loop to outside the parser, retaining control. The callbacks are executed in the same manner, just that now, when there is no left to parse, instead of taking more data from a source on it's own, the parser returns control to you. $p->parse_start; # you can omit this - parse_start will # be called automatically as needed while(defined(my $buffer = get_more_xml())) { $p->parse_more($buffer); } $p->parse_done; This module is a subclass of L which is to L as L is to L itself. =head1 METHODS =over 4 =item parse_string STRING =item parse_more STRING These have the same effect, except that parse_more actually calls parse_string with @_. You might want to use parse_string because in theory it's more efficient. This simply continues parsing with the new string, and sends SAX events for the data that is complete in the string. =item parse_start This calls parse_start on the underlying XML::Parser::ExpatNB object. It's called implicitly when you first call parse_string, though, so you don't have to worry about it. =item parse_done This calls parse_done on the underlying XML::Parser::ExpatNB object. You use it to tell the parser you have no more data to give it. =item parse This is used internally as a sort of parse-anything method. Don't use it, instead use C, which invokes this method correctly, and takes simpler options. =back =head1 SEE ALSO L, L, L, L =head1 VERSION CONTROL This module is maintained using Darcs. You can get the latest version from L, and use C to commit changes. =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT & LICENSE Copyright (c) 2005 Yuval Kogman. All rights reserved This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut XML-SAX-Expat-Incremental-0.05/Makefile.PL0000644000076500007650000000203510267456303022727 0ustar nothingmuchnothingmuch00000000000000#!/usr/bin/perl -w use strict; use ExtUtils::MakeMaker; WriteMakefile( NAME => 'XML::SAX::Expat::Incremental', VERSION_FROM => 'lib/XML/SAX/Expat/Incremental.pm', (eval { ExtUtils::MakeMaker->VERSION("6.18") } ? (SIGN => 1) : ()), AUTHOR => 'Yuval Kogman', ABSTRACT => 'Incremental/non-blocking SAX Driver for Expat', PREREQ_PM => { "XML::SAX::Expat" => '0', # which implies "XML::Parser" => '0', "Test::Exception" => '0', "Test::More" => '0', }, ); __END__ # according to: https://rt.cpan.org/Ticket/Display.html?id=13764 this is broken ## add ourselves to the list of installed parsers sub MY::install { package MY; my $script = shift->SUPER::install(@_); $script =~ s/install :: (.*)$/install :: $1 install_sax_expat_inc/m; $script .= <<"INSTALL"; install_sax_expat_inc : \t\@\$(PERL) -MXML::SAX -e "XML::SAX->add_parser(q(XML::SAX::Expat::Incremental))->save_parsers()" INSTALL return $script; } XML-SAX-Expat-Incremental-0.05/MANIFEST0000644000076500007650000000017110673655310022105 0ustar nothingmuchnothingmuch00000000000000Changes lib/XML/SAX/Expat/Incremental.pm Makefile.PL MANIFEST This list of files META.yml SIGNATURE t/basic.t t/incr.t XML-SAX-Expat-Incremental-0.05/META.yml0000644000076500007650000000104210673655333022230 0ustar nothingmuchnothingmuch00000000000000--- #YAML:1.0 name: XML-SAX-Expat-Incremental version: 0.05 abstract: Incremental/non-blocking SAX Driver for Expat license: ~ generated_by: ExtUtils::MakeMaker version 6.32 distribution_type: module requires: Test::Exception: 0 Test::More: 0 XML::Parser: 0 XML::SAX::Expat: 0 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.2.html version: 1.2 author: - Yuval Kogman XML-SAX-Expat-Incremental-0.05/SIGNATURE0000644000076500007650000000215410673655336022253 0ustar nothingmuchnothingmuch00000000000000This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.55. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 57013707605229ac99ff85fcef0cc03f5244f187 Changes SHA1 4bef7cfff57ff46069e3dc78f9d5bf0075ed2403 MANIFEST SHA1 92e0aacc11cd1588df5c852dbdf0d61d9a7a1c2f META.yml SHA1 9770a7f921af4d62b2146fbc78f9505453136e13 Makefile.PL SHA1 bbbd63a3e4ca1199837c90ead4190d962f0f0b07 lib/XML/SAX/Expat/Incremental.pm SHA1 f7376fd5701446ceb6c9249e43946ef1800fa115 t/basic.t SHA1 6da947e3423e6f4abc55da961452185b636bc3c0 t/incr.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) iD8DBQFG71rbVCwRwOvSdBgRAluzAJ0RSRUBQyemZrhWq4uQsh1aHhRXawCfYaiL DlDxIyzHjQT8fYF5Bn5wrVU= =qAJX -----END PGP SIGNATURE----- XML-SAX-Expat-Incremental-0.05/t/0000755000076500007650000000000010673655333021225 5ustar nothingmuchnothingmuch00000000000000XML-SAX-Expat-Incremental-0.05/t/basic.t0000644000076500007650000000110310170061113022441 0ustar nothingmuchnothingmuch00000000000000#!/usr/bin/perl # pretty much the example test from L use Test::More tests => 3; use XML::SAX; use XML::SAX::PurePerl::DebugHandler; XML::SAX->add_parser(q(XML::SAX::Expat::Incremental)); local $XML::SAX::ParserPackage = 'XML::SAX::Expat::Incremental'; isa_ok( my $handler = XML::SAX::PurePerl::DebugHandler->new(), "XML::SAX::PurePerl::DebugHandler", ); isa_ok( my $parser = XML::SAX::ParserFactory->parser(Handler => $handler), "XML::SAX::Expat::Incremental", ); $parser->parse_string(""); ok($handler->{seen}{start_element}, "parsed something"); XML-SAX-Expat-Incremental-0.05/t/incr.t0000644000076500007650000000336310170061124022327 0ustar nothingmuchnothingmuch00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 16; use Test::Exception; use XML::SAX; use XML::SAX::PurePerl::DebugHandler; XML::SAX->add_parser(q(XML::SAX::Expat::Incremental)); local $XML::SAX::ParserPackage = 'XML::SAX::Expat::Incremental'; isa_ok( my $handler = XML::SAX::PurePerl::DebugHandler->new(), "XML::SAX::PurePerl::DebugHandler", ); isa_ok( my $parser = XML::SAX::ParserFactory->parser(Handler => $handler), "XML::SAX::Expat::Incremental", ); dies_ok { $parser->parse_file(\*DATA) } "can't parse from filehandle"; dies_ok { $parser->parse_done; } "can't parse_done without having started"; my @lines = ; $parser->parse_string(shift @lines); is($handler->{seen}{start_element}, 1, "parsed one elem"); ok(!$handler->{seen}{end_element}, "nothing ended yet"); dies_ok { $parser->parse_start; } "can't start after having started"; $parser->parse_string(shift @lines); is($handler->{seen}{start_element}, 3, "two elements started"); is($handler->{seen}{end_element}, 2, "two closed"); $parser->parse_string(shift @lines); is($handler->{seen}{start_element}, 4, "one more opened"); ok($handler->{seen}{characters}, "at least some character data by now"); is($handler->{seen}{end_element}, 3, "one more closed"); my $line = shift @lines; $parser->parse_string(substr($line, 0, 3, '')); # "{seen}{end_element}, 3, "nothing closed after adding half a close tag"); $parser->parse_string($line); is($handler->{seen}{end_element}, $handler->{seen}{start_element}, "root element closed"); $parser->parse_done; ok($handler->{seen}{end_document}, "document ended"); lives_ok { $parser->parse_start; } "now that we're done we can start a new parse"; __DATA__ ding