Question

The program below gives me weird output that I cannot explain:

use strict;
use warnings;
use XML::Twig;

my $xml = 
q{<block>
    <foo>bar baz</foo>
</block>};

my $twig = XML::Twig->new(
        TwigHandlers => {foo => \&foo, block => \&block},
    );

print "after parse: " . $twig->parse($xml)->sprint;


sub foo {
    my ( $twig, $foo ) = @_;

    my $text = $foo->sprint("don't print outside element");
    my $newSummary = XML::Twig::Elt->parse( '<p><i>' . $text . '</i></p>' );
    $newSummary->paste( 'before', $foo);
    my $parent = $foo->parent;
    # $foo->delete;
    print "foo: " . $parent->sprint . "\n\n";
}

sub block {
    my ($twig, $block) = @_;
    print "block: " . $block->sprint . "\n\n";
}

It prints the following:

foo: <block><p><i>bar baz</i></p><foo>bar baz</foo></block>

block: <block><p><i>bar baz</i></p><foo>bar baz</foo></block>

after parse: <block><foo>bar baz</foo></block>

So I am modifying the twig inside of the foo handler, the change is sticking around for the block handler to see it, but then when processing is all done, the change goes away. What is going on here? How can I make my change stick for the lifetime of the twig?

Was it helpful?

Solution

It looks like a bug, or at least a problem with scoping: the new element seems to be garbage collected when the parse finishes.

One way to avoid this is to add a copy to the creation of the element:

my $newSummary = XML::Twig::Elt->parse( '<p><i>' . $text . '</i></p>' )->copy;

OTHER TIPS

You aren't returning anything. Remove the print statements in your sub routines and you will get the following output:

after parse: <block><p><i>bar baz</i></p><foo>bar baz</foo></block>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top