Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Handler communication in XML::Twig

by diotalevi (Canon)
on Feb 12, 2004 at 17:29 UTC ( #328610=perlquestion: print w/ replies, xml ) Need Help??
diotalevi has asked for the wisdom of the Perl Monks concerning the following question:

How do I communicate @HOGS from &view_handler to find_hidden_views_with_resortable_indexes( $db ) without having to use a global? I'm certain there is a normal XML::Twig facility or an idiomatic way to do this. Am I expected to pass in closures to XML::Twig->new? I think it'd be nice to share the same parser across the program instead of having to recreate it during the loop.

Updates Fixed a bug where @hogs was returned but @HOGS was tested. Also replaced @HOGS = () with local @HOGS.

use strict; use warnings; use vars qw(@HOGS $TWIG $DEFAULT_SERVER); use Notes::OLE (); use File::Basename (); use File::Temp (); use XML::Twig; use YAML (); $DEFAULT_SERVER = 'dev1'; exit main( @ARGV ); =pod <database> <view name='(...)'> <column resort='...'/> </view> </database> INTO server: filepath: view name: WHERE view name starts with ( and ends with ) and has a column with a resort attribute. =cut sub main { my $server = shift(@_) || $DEFAULT_SERVER; $TWIG = XML::Twig->new( twig_handlers => { q[view[@name =~ /^\(.+?\)$/]] => \&handle_view }, twig_roots => { view => 1, column => 1 } ); my %hogs; for my $dbp ( Notes::OLE::server_databases( $server ) ) { my $db = $Notes::OLE::S->GetDatabase( $dbp->{'server'}, $dbp->{'filepath'} ) or next; my @hogs = find_hidden_views_with_resortable_indexes( $db ); if ( @hogs ) { $hogs{ $dbp->{'server'} }{ $dbp->{'filepath'} } = [ @hogs ]; } } my $output = File::Basename::basename( $0 ); $output =~ s/\.[^.]+$/.yml/; YAML::DumpFile( $output, \%hogs ); my $editor = $ENV{'EDITOR'} || 'notepad'; system( $editor, $output ); return 1; } sub find_hidden_views_with_resortable_indexes { my $db = shift; # Input my $notes = $db->CreateNoteCollection( 0 ); $notes->{'SelectViews'} = 1; $notes->BuildCollection; # Output my $temp_file = File::Temp::tmpnam(); my $stream = $Notes::OLE::S->CreateStream; $stream->Open( $temp_file ); # Exporter my $exporter = $Notes::OLE::S->CreateDXLExporter( $notes, $stream +); $exporter->Process; # Cleanup so there are no open handles to the file $stream->Close; # Run XML::Twig on the exported schema local @HOGS; $TWIG->parsefile( $temp_file ); $TWIG->purge; # Remove the exported schema unlink $temp_file or warn "Couldn't delete $temp_file: $!"; return @HOGS; } sub handle_view { my ($t, $view) = @_; my $name = $view->att( 'name' ); push @HOGS, $name if $view->children( 'column[@resort]' ); return 1; }

janitored by ybiC: Balanced <readmore> tags around the codeblock, to reduce vertical scrolling on Monastery front page

Comment on Handler communication in XML::Twig
Select or Download Code
Re: Handler communication in XML::Twig
by mirod (Canon) on Feb 12, 2004 at 17:41 UTC

    Indeed you can pass closures to new.

    Have a look at Simon Cozens' Achieving Closure, which explains the process in great detail.

    Basically you can do this:

    my $t= XML::Twig->new( twig_handlers => { foo => sub { my_handler( @_, + @HOGS) } }); # ... sub my_handler { my( $t, $elt, @HOGS)= @_; # I would probably pass \@HOGC though
      Do you use it that way or are you just confirming the possible? I'm after the method good X'T users use. I don't know how heavy the twig object and whether it would be preferred to retain the existing object.

        I use it a lot that way.

        I have never benchmarked the creation of the object itself, as I the type of code I write rarely parses a lot of files.

Re: Handler communication in XML::Twig
by Fletch (Chancellor) on Feb 12, 2004 at 17:44 UTC

    Or you could always define @HOGS in a lexical scope that just your two handlers can see.

    { my @HOGS; sub find_hiden_views { ... } sub handle_view { ... } }
      This doesn't solve the problem and turns @HOGS into a tricky sort of global-alike.
Re: Handler communication in XML::Twig
by PodMaster (Abbot) on Feb 12, 2004 at 17:56 UTC
    See "Private Attributes" in the XML::Twig docs.
    Attributes with a name starting with # (illegal in XML) will not be output, so you can safely use them to store temporary values during processing.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      I saw that but don't think it is meant for this sort of problem. That requires that I write into some "other" scratch area of the document currently being parsed. I'd do this in an obfu but not for production code.

      Note that you can store anything in a private attribute, not just text, it's just a regular Perl variable, so an array ref is perfectly OK. (note to self, add this to the docs... done ;--)

        This is just an FYI but I didn't get the sense from the documentation that this was something to be used as a shared scratchpad. On re-reading it just now it occurs to me that I don't know what the private attribute is supposed to be written to or what its lifetime is.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://328610]
Approved by kvale
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2014-07-12 22:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (241 votes), past polls