#!/usr/bin/perl -w use XML::Parser; use Getopt::Long; use Date::Parse; use Date::Format; use YAML; =head1 SYNOPSIS gasInfo.pl - extract fuel-use statistics from a GNUcash account =cut $gasAcctGuid = '251ece66fd136c8f1c212f84392cc9ef' ; GetOptions("out|o=s" => \$out, "accountGuid|acctGuid|guid|g=s" => \$gasAcctGuid ); $file = shift @ARGV if scalar @ARGV == 1; $file = "household.xac" if !defined $file; open FILE, "gunzip <$file |" or die "Couldn't open '$file'"; if (defined $out) { open STDOUT, ">$out" or die "Couldn't open '$out' for writing"; } sub handle_init; sub handle_start; sub handle_char; sub handle_end; sub handle_final; $tranData = { isGas => 0 }; $splitData = {}; $parser = new XML::Parser(Handlers => { Init => \&handle_init, Start =>\&handle_start, Char => \&handle_char, End => \&handle_end, Final =>\&handle_final } ); $parser->parse(*FILE); exit 0; sub handle_init { print "date,gallons,miles,cost\n"; } sub handle_start { my ($expat,$element,%attrs) = @_; if ($element eq 'gnc:transaction') { $tranData = { isGas => 0 }; } elsif ($element eq 'trn:split') { $splitData = {}; } } sub handle_char { my ($expat, $text) = @_; if ($expat->current_element eq 'trn:description') { $tranData->{description} = $text; } elsif ($expat->current_element eq 'split:account') { $splitData->{account} = $text; } elsif ($expat->current_element eq 'split:value') { $splitData->{value} = eval( $text . '.0' ); } elsif ($expat->current_element eq 'ts:date' and ($expat->context)[-2] eq 'trn:date-posted') { $tranData->{date} = $text; } } sub handle_end { my ($expat, $element) = @_; if ($element eq 'gnc:transaction' and $tranData->{isGas}) { my $FIXP = "\\d+[.]\\d*|\\d*[.]\\d+"; if ($tranData->{description} =~ /Gas.*-.*?($FIXP) *gal.*-.*?($FIXP) mi/) { my $gallons = 0.0+$1; my $miles = 0.0+$2; print join(",", substr($tranData->{date},0,10), sprintf("%.3f",$gallons), sprintf("%.1f",$miles), sprintf("%.2f",$tranData->{value}) ), "\n"; } $tranData = { isGas => 0 }; } elsif ($element eq 'trn:split' and $splitData->{account} eq $gasAcctGuid) { $tranData->{isGas} = 1; $tranData->{value} = $splitData->{value}; $splitData = {}; } } sub handle_final { ; }