#!/usr/bin/perl -lw
use strict;
use XML::Simple;
use Data::Traverse;

my $data= XMLin( \*DATA);
my $t= Data::Traverse->new( $data);

# print the initial adresses
print "initial addresses:";
$t->traverse( \&dump_addresses); 

# update the addresses
# you need to use $_[1] in order to modify the origiinal data structure
print "\nupdating...\n";
$t->traverse( sub { return $_[0]->prune if( server_name( $_[0]) eq 'kalahari');
                    $_[1]=~ s{10\.0\.0\.}{192.168.1} 
                      if( $_[0]->is_scalar && $_[0]->path_matches( '/address'));
                  }
            );

# did it work?
print "updated addresses:";
$t->traverse( \&dump_addresses); 

sub dump_addresses
  { my( $t, $item)= @_;
    if( my $server_name= server_name( $t)) { print "  $server_name"; }
    print "    $_" if( $t->is_scalar && $t->path_matches( '/address')); 
  }

sub server_name
  { my( $t)= @_;
    if( $t->parent_item_key && ($t->parent_item_key eq 'server'))
      { return $t->item_key; }
    else
      { return ''; }
  }
    


__DATA__
<config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
  <server name="sahara" osname="solaris" osversion="2.6">
    <address>10.0.0.101</address>
    <address>10.0.1.101</address>
  </server>
  <server name="gobi" osname="irix" osversion="6.5">
    <address>10.0.0.102</address>
  </server>
  <server name="kalahari" osname="linux" osversion="2.0.34">
    <address>10.0.0.103</address>
    <address>10.0.1.103</address>
  </server>
</config>

