http://qs1969.pair.com?node_id=308725

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Is there a way to walk through an XML file? I want to parse an XML file line-by-line, taking action depending on the tag found. I'm making a simple backup script that will back up filesystems as well as {My | Postgre}SQL databases. The config file would look like this:
<config> <logprefix>/var/log/sbackup</logprefix> <storage>/home/backups</storage> <item name = "SomeDatabase" type="MySQLDB"> <dbName>SomeDatabase</dbName> <dbUser>SomeUser</dbuser> <dbPass>password</dbPass> </item> <item name = "SomeFilesFiles" type="Filesystem"> <path>/home/globalherald</path> </item> </config>
I tried using XML::Simple, dumping the contents into a hash structure, and walking through that, but I've done something wrong. Is what I'm trying to do possible? Here's the script:
#!/usr/bin/perl # sbackup.pl: Backing up the server. Looks for a file # called sbackup.xml in /etc which specifies, which databases # and which directories to back up. # # TODO: # Add tar/database dump logs to logs # Add postgresql dumper # Add tar/database dump options to XML use strict; use warnings; use XML::Simple; use IO::File; use vars qw($XMLConfig $logprefix $fh); sub LogMsg { my $consecho = 1; my $deadly = shift; my $message = shift; my $timestamp = localtime(time); open LogFile, ">>$logprefix/sbackup.log" || die "Can't open logfil +e!"; print LogFile "$timestamp: $message\n"; if ($consecho == 1) { print "$timestamp: $message\n"; } return; } sub ParseConfig { $fh = new IO::File('/etc/sbackup.xml') or LogMsg(1, "Can't open sb +ackup.xml!"); $XMLConfig = XMLin($fh); return; } sub BackupMysqlDatabase { my $item = shift; my $dbname = shift; my $dbuser = shift; my $dbpass = shift; my $command = "mysqldump --quick --add-locks --add-drop-table -a - +e -F -K -u $dbuser -p $dbpass $dbname"; #my $result = system($command); print $command; my $result = 0; if ($result == 0) { LogMsg(0, "Backup of $item, database $dbname successful!"); } else { LogMsg(0, "Backup of $item, database $item failed!"); } return; } sub BackupFS { my $item = shift; my $frompath = shift; my $storage = shift; my $command = "tar cf $storage/$item.tar $frompath"; #my $result = system($command); print $command; my $result = 0; if ($result == 0) { LogMsg(0, "Backup of $item, pathname $frompath successful!"); } else { LogMsg(0, "Backup of $item, pathname $frompath failed!"); } return; } my $localstorage; my %currentFS = ("item", "", "source", "") ; my %currentDB = ("item", "", "dbname", "", "dbuser", "", "dbpass", "" +); my $currentitem; ParseConfig(); foreach my $element ($XMLConfig) { print "The element is $element!\n"; my %somehash = {$element}; my @hashkeys = keys %somehash; print "Keys are: @hashkeys\n"; if ($element eq "Logprefix") { $logprefix = $XMLConfig->logprefix; } if ($element eq "Storage") { $localstorage = $XMLConfig->storage; } if ($element eq "Item") { if ($element->{type} eq "MySQLDB") { foreach my $element2 ($element) { if ($element2 eq "DbName") { $currentDB{item} = $element->{item}; $currentDB{dbname} = $element2->{DbName}; } if ($element2 eq "DbUser") { $currentDB{dbuser} = $element2->{DbUser}; } if ($element2 eq "DbPass") { $currentDB{dbpass} = $element2->{DbPass}; } } BackupMySQLDatabase($currentDB{item}, $currentDB{dbname}, +$currentDB{dbuser}, $currentDB{dbpass}); } if ($element->{type} eq "Filesystem") { foreach my $element2 ($element) { if ($element2 eq "Path") { $currentFS{item} = $element->{Item}; $currentFS{path} = $element2->{Path}; } } BackupFS($currentFS{item}, $currentFS{path}, $localstorage +); } } } close ($fh);
Thanks everybody!