XML :: Twig - set_text without clobbering structure

Using XML::Twigusing the method set_text- a warning appears:

set_text ($ string) Set the text for the element: if this element is PCDATA, just set its text, otherwise cut out all the children of this element and create one PCDATA child disk for it that contains the text.

So, if I want to do something simple, for example, say, changing all the text in an XML :: Document:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented_a',
    'twig_handlers' => {
        '_all_' => sub {
            my $newtext = $_->text_only;
            $newtext =~ tr/[a-z]/[A-Z]/;
            $_->set_text($newtext);
        }
    }
);
$twig->parse( \*DATA );
$twig->print;

__DATA__
<root>
    <some_content>fish
        <a_subnode>morefish</a_subnode>
    </some_content>
    <some_more_content>cabbage</some_more_content>
</root>

This - due to the set_textreplacement of children - is reset to:

<root></root>

But if I focus on only one (lower level) node (e.g. a_subnode), then it works fine.

/ , ? , - , ... , . (, ?)

( - , , - "" ).

, , node cut/and/paste ( , , ), .

+4
2

, _all_, : #TEXT text_only text. .

update. char_handler : char_handler => sub { uc shift }, .

+4

:

  • .
  • cut .
  • .
  • paste .

, , , :

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;
use Data::Dumper;

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

    my $newtext = $element->text_only;
    my @children;
    foreach my $child ( $element->children ) {
        if ( not $child->tag eq "#PCDATA" ) {
            push( @children, $child->cut );
        }
    }
    $newtext =~ tr/[a-z]/[A-Z]/;
    $element->set_text($newtext);

    $_->paste( 'last_child', $element ) for @children;
}

my $twig =
    XML::Twig->new( 'twig_handlers' => { '_all_' => \&replace_text, } );
$twig->parse( \*DATA );

print "Result:\n";
$twig->print;

__DATA__
<root>
    <some_content>fish
        <a_subnode>morefish</a_subnode>
    </some_content>
    <some_more_content>cabbage</some_more_content>
</root>

:

<root><some_content>FISH
        <a_subnode>MOREFISH</a_subnode></some_content><some_more_content>CABBAGE</some_more_content></root>

, , - .

:

XML::Twig -> new ( 'pretty_print' => 'indented_a' ) -> parse ( $twig -> sprint ) -> print;

, . ( )

<root>
  <some_content>FISH
        <a_subnode>MOREFISH</a_subnode></some_content>
  <some_more_content>CABBAGE</some_more_content>
</root>
+2

All Articles