in reply to Twig delete not deleting the entire section?

When you're deleting the node, the remaining address and contact elements haven't been parsed yet, so they aren't removed.

Create a handler for the node you want to remove. Unfortunately, you can't use something like

site[name[string() =~ /name2/]]
because XML::Twig doesn't support the full XPath syntax:

> XPath expressions are limited to using the child and descendant axis (indeed you can't specify an axis), and predicates cannot be nested.

You can do part of the work in Perl, though:

my %handlers = ( 'site' => sub { my ($twig, $cnt) = @_; $cnt->delete if grep $_->text =~ /name2/, $cnt->children('name'); } );

BTW, in XML::XSH2, you'd just

delete /sites/site[xsh:match(name,"name2")] ;
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

Replies are listed 'Best First'.
Re^2: Twig delete not deleting the entire section?
by paisani (Acolyte) on Mar 14, 2018 at 17:33 UTC
    That would be a straight up bug, wouldn't it? But I'm not sure that's right. I think we may be missing something because first it does delete the closing /site tag, plus, this below should have worked then because I'm specifically parsing the children -
    use strict; use warnings; use XML::Twig; my $xml = q( <sites> <site siteid="ONE"> <name>name1</name> <address>address1</address> <contact>contact1</contact> </site> <site siteid="TWO"> <name>name2</name> <address>address2</address> <contact>contact2</contact> </site> </sites> ); my %handlers = ( 'name[string() =~ /name2/]' => sub { my ($twig, $cnt) = @_; my $parent = $cnt->parent; foreach ($parent->children) { print "Deleting: " . $_->text . "\n"; $_->delete; } $parent->delete; } ); my $twig= new XML::Twig( PrettyPrint => 'indented', twig_handlers => + \%handlers); $twig->parse($xml); print $twig->sprint;
    Gave the following output -
    Deleting: name2 <sites> <site siteid="ONE"> <name>name1</name> <address>address1</address> <contact>contact1</contact> </site> <address>address2</address> <contact>contact2</contact> </sites>

      When the handler triggers on name only

      <site siteid="TWO"> <name>name2</name>

      has been parsed so name is the only child the parent has.

      Add a $cnt->parent->print statement to see it. If you change the order of elements your original code works.

      <sites> <site siteid="ONE"> <name>name1</name> <address>address1</address> <contact>contact1</contact> </site> <site siteid="TWO"> <address>address2</address> <contact>contact2</contact> <name>name2</name> </site> </sites>

      If the handler is on site like choroba said, that is triggered after all the children have been parsed.

      poj