|
NAMEXML::SAX::Machine - Manage a collection of SAX processorsVERSIONversion 0.46SYNOPSIS## Note: See XML::SAX::Pipeline and XML::SAX::Machines first, ## this is the gory, detailed interface. use My::SAX::Machines qw( Machine ); use My::SAX::Filter2; use My::SAX::Filter3; my $filter3 = My::SAX::Filter3->new; ## A simple pipeline. My::SAX::Filter1 will be autoloaded. my $m = Machine( # # Name => Class/object => handler(s) # [ Intake => "My::SAX::Filter1" => "B" ], [ B => My::SAX::Filter2->new() => "C" ], [ C => $filter3 => "D" ], [ D => \*STDOUT ], ); ## A parser will be created unless My::SAX::Filter1 can parse_file $m->parse_file( "foo.revml" ); my $m = Machine( [ Intake => "My::SAX::Filter1" => qw( Tee ) ], [ Tee => "XML::Filter::SAXT" => qw( Foo Bar ) ], [ Foo => "My::SAX::Filter2" => qw( Out1 ) ], [ Out1 => \$log ], [ Bar => "My::SAX::Filter3" => qw( Exhaust ) ], ); DESCRIPTIONWARNING: This API is alpha!!! It will be changing.A generic SAX machine (an instance of XML::SAX::Machine) is a container of SAX processors (referred to as "parts") connected in arbitrary ways. Each parameter to "Machine()" (or "XML::SAX::Machine-"new()>) represents one top level part of the machine. Each part has a name, a processor, and one or more handlers (usually specified by name, as shown in the SYNOPSIS). Since SAX machines may be passed in as single top level parts, you can also create nested, complex machines ($filter3 in the SYNOPSIS could be a Pipeline, for example). A SAX machines can act as a normal SAX processors by connecting them to other SAX processors: my $w = My::Writer->new(); my $m = Machine( ...., { Handler => $w } ); my $g = My::Parser->new( Handler => $w ); Part NamesAlthough it's not required, each part in a machine can be named. This is useful for retrieving and manipulating the parts (see "part", for instance), and for debugging, since debugging output (see "trace_parts" and "trace_all_parts") includes the names.Part names must be valid Perl subroutine names, beginning with an uppercase character. This is to allow convenience part accessors methods like $c = $m->NameOfAFilter; to work without ever colliding with the name of a method (all method names are completely lower case). Only filters named like this can be accessed using the magical accessor functions. Reserved Names: Intake and ExhaustThe names c<Intake> and "Exhaust" are reserved. "Intake" refers to the first part in the processing chain. This is not necessarily the first part in the constructor list, just the first part to receive external events."Exhaust" refers to the output of the machine; no part may be named "Exhaust", and any parts with a handler named "Exhaust" will deliver their output to the machine's handler. Normally, only one part should deliver it's output to the Exhaust port. Calling $m->set_handler() alters the Exhaust port, assuming any processors pointing to the "Exhaust" provide a "set_handler()" method like XML::SAX::Base's. "Intake" and "Exhaust" are usually assigned automatically by single-purpose machines like XML::SAX::Pipeline and XML::SAX::Manifold. SAX Processor SupportThe XML::SAX::Machine class is very agnostic about what SAX processors it supports; about the only constraint is that it must be a blessed reference (of any type) that does not happen to be a Perl IO::Handle (which are assumed to be input or output filehandles).The major constraint placed on SAX processors is that they must provide either a "set_handler" or "set_handlers" method (depending on how many handlers a processor can feed) to allow the SAX::Machine to disconnect and reconnect them. Luckily, this is true of almost any processor derived from XML::SAX::Base. Unfortunately, many SAX older (SAX1) processors do not meet this requirement; they assume that SAX processors will only ever be connected together using their constructors. ConnectionsSAX machines allow you to connect the parts however you like; each part is given a name and a list of named handlers to feed. The number of handlers a part is allowed depends on the part; most filters only allow once downstream handler, but filters like XML::Filter::SAXT and XML::Filter::Distributor are meant to feed multiple handlers.Parts may not be connected in loops ("cycles" in graph theory terms). The machines specified by: [ A => "Foo" => "A" ], ## Illegal! and [ A => "Foo" => "B" ], ## Illegal! [ B => "Foo" => "A" ], . Configuring a machine this way would cause events to flow in an infinite loop, and/or cause the first processor in the cycle to start receiving events from the end of the cycle before the input document was complete. Besides, it's not a very useful topology :). SAX machines detect loops at construction time. NAMEXML::SAX::Machine - Manage a collection of SAX processors APIPublic MethodsThese methods are meant to be used by users of SAX machines.
Events and parse routinesXML::SAX::Machine provides all SAX1 and SAX2 events and delgates them to the processor indicated by $m->find_part( "Intake" ). This adds some overhead, so if you are concerned about overhead, you might want to direct SAX events directly to the Intake instead of to the machine.It also provides parse...() routines so it can whip up a parser if need be. This means: parse(), parse_uri(), parse_string(), and parse_file() (see XML::SAX::EventMethodMaker for details). There is no way to pass methods directly to the parser unless you know that the Intake is a parser and call it directly. This is not so important for parsing, because the overhead it takes to delegate is minor compared to the effort needed to parse an XML document. Internal and Helper MethodsThese methods are meant to be used/overridden by subclasses.
TODO
LIMITATIONSAUTHORBarrie Slaymaker <barries@slaysys.com> LICENSEArtistic or GPL, any version.AUTHORS
COPYRIGHT AND LICENSEThis software is copyright (c) 2013 by Barry Slaymaker.This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
Visit the GSP FreeBSD Man Page Interface. |