Finance-OFX

 view release on metacpan or  search on metacpan

lib/Finance/OFX/Parse.pm  view on Meta::CPAN


    if( ref($tree) eq 'ARRAY' )
    {
	parse_dates($_) for @{$tree};
    }
    elsif( ref($tree) eq 'HASH' )
    {
	for( keys %{$tree} )
	{
	    if( /^dt/ )
	    {
		# Add seconds spacer
		$tree->{$_} =~ s/^([0-9]{12})([0-9]{2})/$1:$2/;
		# Add minutes spacer
		$tree->{$_} =~ s/^([0-9]{10})([0-9]{2})/$1:$2/;
		# Add date spacers
		$tree->{$_} =~ s/^([0-9]{4})([0-9]{2})([0-9]{2})/$1-$2\-$3 /;
		# Add a leading zero to the timezone offset, if needed
		$tree->{$_} =~ s/\[([-+]?)([0-9]):[A-Z]{3}\]/ $1\x30$2\x30\x30/;
		# Handle timezone offsets that were already 2 digits
		$tree->{$_} =~ s/\[([-+]?)([0-9]{1,2}):[A-Z]{3}\]/ $1$2\x30\x30/;
		# Do the conversion
		$tree->{$_} = str2time($tree->{$_}, 'GMT');
	    }
	    else
	    {
		parse_dates($tree->{$_});
	    }
	}
    }
}

sub parse
{
    $_[0] =~ s/\x0D//g;			# Un-networkify newlines

    my ($header, $body) = split /\n\n/, shift, 2;

    # Parse the OFX header block
    $header =~ s/^\s//;				# Strip leading whitespace
    my %header = split /[:\n]/, $header;	# Convert to a hash

    return undef unless ($header{OFXHEADER} == '100') and ($header{DATA} eq 'OFXSGML');

    my $tree = Finance::OFX::Tree::parse($body);
    return undef unless $tree and ($tree->[0]{name} eq 'ofx');

    $tree = collapse($tree);		# Collapse the parse tree into a hash
    parse_dates($tree);			# Convert date elements to Unix time

    # Merge the header hash into the parse tree
    $tree->{header} = \%header;

    return $tree;
}

sub parse_file
{
    my $file = shift;
    return undef unless $file;
#    my $text = do { local(@ARGV, $/) = $file; <> };
    my $text = read_file($file);
    return undef unless $text;
    return parse($text);
}

1;

__END__

=head1 NAME

Finance::OFX::Parse - Parse the Open Financial Exchange protocol

=head1 SYNOPSIS

 use Finance::OFX::Parse
 my $tree = Finance::OFX::Parse::parse($ofxContent);

=head1 DESCRIPTION

C<Finance::OFX::Parse> provides two functions, C<parse()> and C<parse_file()>, that 
accept an OFX "file" and return a reference to a hash tree representing the 
contents of the file. C<parse()> expects the OFX content as a scalar argument 
while C<parse_file> expects a filename.

Parsing well-formed OFX content returns a hash with two keys: 'ofx' and 
'header'. The 'ofx' key is a reference to a hash tree representing the <OFX> block 
and the 'header' key is a reference to a hash of header attributes. All date 
values are automatically converted to UNIX time.

=head2 EXAMPLE

If C<$ofxContent> in the above code is...

 OFXHEADER:100
 DATA:OFXSGML
 VERSION:102
 SECURITY:NONE
 ENCODING:USASCII
 CHARSET:1252
 COMPRESSION:NONE
 OLDFILEUID:NONE
 NEWFILEUID:NONE

 <OFX>
    <SIGNONMSGSRSV1>
 	<SONRS>
 	    <STATUS>
 		<CODE>0
 		<SEVERITY>INFO
 		<MESSAGE>SonRq is successful
 	    </STATUS>
 	    <DTSERVER>20080220142819.321[-8:PST]
 	    <LANGUAGE>ENG
 	    <FI>
 		<ORG>DI
 		<FID>074014187
 	    </FI>
 	</SONRS>
    </SIGNONMSGSRSV1>



( run in 1.317 second using v1.01-cache-2.11-cpan-800906f7e73 )