package XML::SAX::Pipeline; =head1 NAME XML::SAX::Pipeline - Manage a linear pipeline of SAX processors =head1 SYNOPSIS use XML::SAX::Pipeline qw( Pipeline ); use XML::Fitler::Foo; my $m = Pipeline( XML::Filter::Foo->new, ## Create it manually "XML::Filter::Bar", ## Or let Pipeline load & create it "XML::Filter::Baz", { ## Normal options Handler => $h, } ); ## To choose the default parser automatically if XML::Filter::Foo ## does not implement a parse_file method, just pretend the Pipeline ## is a parser: $m->parse_file( "blah" ); ## To feed the pipeline from an upstream processor, treat it like ## any other SAX filter: my $p = Some::SAX::Generator->new( Handler => $m ); ## To read a file or the output from a subprocess: my $m = Pipeline( "outfile.txt" ); my $m = Pipeline( ..., "| xmllint --format -" ); =head1 DESCRIPTION An XML::SAX::Pipeline is a linear sequence SAX processors. Events passed to the pipeline are received by the C end of the pipeline and the last filter to process events in the pipeline passes the events out the C to the filter set as the pipeline's handler: +-----------------------------------------------------------+ | An XML:SAX::Pipeline | | Intake | | +---------+ +---------+ +---------+ Exhaust | --+-->| Stage_0 |--->| Stage_1 |-->...-->| Stage_N |----------+-----> | +---------+ +---------+ +---------+ | +-----------------------------------------------------------+ As with all SAX machines, a pipeline can also create an ad hoc parser (using L) if you ask it to parse something and the first SAX processer in the pipeline can't handle a parse request: +-------------------------------------------------------+ | An XML:SAX::Pipeline | | Intake | | +--------+ +---------+ +---------+ Exhaust | | | Parser |-->| Stage_0 |-->...-->| Stage_N |----------+-----> | +--------+ +---------+ +---------+ | +-------------------------------------------------------+ or if you specify an input file like so: my $m = Pipeline(qw( output_file.xml )); And, thanks to Perl's magic open (see L), you can read and write from processes: my $m = Pipeline( "gen_xml.pl |", "XML::Filter::Bar", "XML::Filter::Baz", "| consume_xml.pl", ); This can be used with an L to place a handy debugging tap in a pipeline (or other machine): my $m = Pipeline( "output_file.xml", ); =cut use base qw( XML::SAX::Machine ); $VERSION = 0.1; use strict; use Carp; =head1 METHODS See L for most of the methods. =over =item new my $pipeline = XML::SAX::Pipeline->new( @processors, \%options ); Creates a pipeline and links all of the given processors together. Longhand for Pipeline(). =cut sub new { my $proto = shift; my $options = @_ && ref $_[-1] eq "HASH" ? pop : {}; my $stage_number = 0; my @machine_spec = map [ "Stage_" . $stage_number++, $_ ], @_; push @{$machine_spec[$_]}, $_ + 1 for 0..$#machine_spec-1 ; $machine_spec[0]->[0] = "Intake" if @machine_spec; push @{$machine_spec[-1]}, "Exhaust" if @machine_spec; return $proto->SUPER::new( @machine_spec, $options ); } =back =head1 AUTHOR Barrie Slaymaker =head1 COPYRIGHT Copyright 2002, Barrie Slaymaker, All Rights Reserved. You may use this module under the terms of the Artistic, GNU Public, or BSD licenses, your choice. =cut 1;