turns into<set> $z <add>$x $y</add> </set>
So in order for my TwigHandlers to fire on the <add> nested inside the <set>, I recursively create a new XML::Twig and parse the small <add> element:$z = $x + $y
and this does in fact work: my TwigHandlers notice the <add> tag and fire. However I have two different behaviors I want from my handlers. Sometimes I want them to print their output and other times I want them to append to a string.{ my $twig = new XML::Twig ( %constructor ) ; $twig->parse($elt->next_elt->sprint); }
this is controlled by a package variable called $pmode. When it is true, then the call to my print routine will print, otherwise it will append to a string. I am altering $pmode by the use of local(), but for some reason, when the TwigHandler for add fires and $pmode has been localized, it instead has the non-localized true version, when it should have the localized false version.
I print $pmode immediately before and after the call to parse in the newly created twig, and it is false in both cases, however when the TwigHandler fires and I print $pmode there, unfortunately it is true... but how this could be is confusing.
and here is a sample xml file#!/usr/local/bin/perl use Data::Dumper; use XML::Twig; ++$|; our $pmode = 1; my $pstring; sub pt { my (@string) = @_; for (@string) { if ($pmode) { print $_; } else { $pstring .= $_; } } } # print expression - no semicolon at end sub pe { pt $_[0] } # print statement - semicolon at end sub ps { pt "$_[0];\n"; } # print statement demux - distribute 1 fish to each of the masses sub ps_dmux { my ($fish, @masses) = @_; map { ps "$fish $_" } @masses; } # print statement with masses as a parenthesized arguement sub ps_pare { my ($fish, @masses) = @_; ps sprintf "$fish (%s)", join ',', @masses; } my %constructor = ( StartTagHandlers => { scope => sub { print "{" }, perl => sub { my $T = $_[1]->att("binary"); printf "#!%s\n", $T }, }, TwigHandlers => { scope => sub { print "}" }, use => sub { my @p = split /\s+/, $_[1]->text; ps_dmux $_[1]->gi +, @p }, my => sub { my @p = split /\s+/, $_[1]->text; ps_pare $_[1]->gi +, @p }, print => sub { my @p = split /\s+/, $_[1]->text; ps_pare $_[1]->gi +, @p }, add => sub { my @p = split /\s+/, $_[1]->text; warn " [add pmode +: $pmode]\ "; pe join '+', @p }, set => sub { my $elt = $_[1]; my @children = $elt->children; if (@children == 1) { ps sprintf "%s = %s", split /\s+/, $elt->text } else { # children == 2 or more { local $pmode; pt $elt->next_elt->text, " = "; $elt = $elt->next_elt; warn " [else pmode : $pmode ] "; my $twig = new XML::Twig ( %constructor ) ; $twig->parse($elt->next_elt->sprint); warn " [else pmode 2 : $pmode ] "; } warn " [ non-local pmode: $pmode ]"; pt $pstring; $pstring = ''; } } } ); my $twig = new XML::Twig ( %constructor ) ; my $file = shift or die "usage: $0 perxml.xml"; $twig->parsefile($file);
</code><perl binary="/usr/bin/perl"> <use>strict warnings diagnostics</use> <scope> <my>$x $y $z</my> <set>$x 111</set> <set>$y 554</set> <set>$z <add>$x $y</add> </set> <print>$z</print> </scope> </perl>
In reply to XML::Twig recursive constructor calls and local() by princepawn
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |