UsefulUserName
UsefulUserName

Reputation: 595

Deleting the first child of every node in an xml file in perl

I've got an XML-file where the first children of a node are all empty, so I would like to delete them using XML::Twig. The XML file might look like this:

<stuff>
    <a>
        <b id=""/>
        <b id="2"/>
        <b id="3"/>
        <b id="4"/>
    </a>
    <a>
        <b id=""/>
        <b id="5"/>
    </a>
    <a>
        <b id=""/>
        <b id="6"/>
        <b id="7"/>
        <b id="8"/>
        <b id="9"/>
        <b id="10"/>
        <b id="11"/>
    </a>
    <a>
        <b id=""/>
        <b id="12"/>
        <b id="13"/>
        <b id="14"/>
    </a>
</stuff>

So what I am trying to do is delete every first <b> child of every given <a> node. The way I've tried to do it is derived from the XML::Twig site on CPAN:

my @a = $root->children('a');
foreach my $delA (@a) {
    $delA->first_child->delete();
}

But it's not working. I don't have a whole lot of experience with Perl, so I am wondering if I misunderstood how the array is build here. Can somebody point out what I am doing wrong and what I should do instead?

Upvotes: 1

Views: 90

Answers (2)

zdim
zdim

Reputation: 66883

Your code works for me, just as it stands.

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

my $file = 'data_sample.xml';
my $t = XML::Twig->new(pretty_print => 'indented');
$t->parsefile( $file );
my $root = $t->root;

my @kids = $root->children('a');
# $_->print for @kids;

foreach my $delA (@kids) {
    $delA->first_child->delete();
}

$_->print for @kids;

The print shows that the empty elements at first_child are gone

<a>
  <b id="2"/>
  <b id="3"/>
  <b id="4"/>
</a>
<a>
  <b id="5"/>
</a>
<a>
  <b id="6"/>
  ...

Upvotes: 1

Sobrique
Sobrique

Reputation: 53478

This seems to do the trick:

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;

my $twig = XML::Twig -> new ( pretty_print => 'indented_a') -> parsefile('sample.xml');

foreach my $element ( $twig -> get_xpath('./a') ) {
   $element -> first_child('b') -> delete;
}
$twig -> print; 

However it looks like you're deleting the nodes with 'null ids'.

So how about:

$_ -> delete for $twig -> get_xpath('./a/b[@id=""]');

(NB: Can use //a if you want 'anywhere within the structure')

Upvotes: 2

Related Questions