Text-CSV-Simple

 view release on metacpan or  search on metacpan

lib/Text/CSV/Simple.pm  view on Meta::CPAN

and ninth entries for each line)

=head2 field_map

	$parser->field_map(qw/id name null town null postcode/);

Rather than getting back a listref for each entry in your CSV file, you
often want a hash of data with meaningful names. If you set up a field_map
giving the name you'd like for each field, then we do the right thing
for you! Fields named 'null' vanish into the ether.

=head1 TRIGGER POINTS

To enable you to make this module do things that I haven't dreamed off
(without you having to bother me with requests to extend the
functionality), we use Class::Trigger to provide a variety of points at
which you can hook in and do what you need. In general these should be
attached to the $parser object you've already created, although you
could also subclass this module and set these up as class data.

Each time we call a trigger we wrap it in an eval block. If the eval
block catches an error we simply call 'next' on the loop. These can
therefore be used for short-circuiting.on certain conditions.

=head2 before_parse

  $parser->add_trigger(before_parse => sub {
    my ($self, $line) = @_;
    die unless $line =~ /wanted/i;
  });

Before we call Text::CSV_XS 'parse' on each line of input text, we call
the before_parse trigger with that line of text.

=head2 after_parse

  $parser->add_trigger(after_parse => sub {
    my ($self, $data) = @_;
    die unless $wanted{$data->[0]};
  });

After we sucessfully call Text::CSV_XS 'parse' on each line of input text,
we call the after_parse trigger with a list ref of the values 

=head2 error

Currenly, for each line that we can't parse, we call the 'failure'
trigger (with the Text::CSV_XS parser object), which emits a warning
and moves on. This happens in an invisible superclass, so you can supply
your own behaviour here:

	$parser->add_trigger(on_failure => sub { 
		my ($self, $csv) = @_;
		warn "Failed on " . $csv->error_input . "\n";
	});

=cut

sub new {
	my $class = shift;
	return bless { _parser => Text::CSV_XS->new(@_), } => $class;
}

sub _parser { shift->{_parser} }

sub _file {
	my $self = shift;
	$self->{_file} = shift if @_;
	return $self->{_file};
}

sub _contents {
	my $self  = shift;
	my @lines = File::Slurp::read_file($self->_file)
		or die "Can't read " . $self->_file;
	return @lines;
}

sub want_fields {
	my $self = shift;
	if (@_) {
		$self->{_wanted} = [@_];
	}
	return @{ $self->{_wanted} || [] };
}

sub field_map {
	my $self = shift;
	if (@_) {
		$self->{_map} = [@_];
	}
	return @{ $self->{_map} || [] };
}

sub read_file {
	my ($self, $file) = @_;
	$self->_file($file);
	my @lines = $self->_contents;
	my @return;
	my $csv = $self->_parser;
	foreach my $line (@lines) {
		eval { $self->call_trigger(before_parse => $line) };
		next if $@;
		next unless $line;
		unless ($csv->parse($line)) {
			$self->call_trigger(on_failure => $csv);
			next;
		}
		my @fields = $csv->fields;
		eval { $self->call_trigger(after_parse => \@fields) };
		next if $@;
		if (my @wanted = $self->want_fields) {
			@fields = @fields[ $self->want_fields ];
		}
		my $addition = [ @fields ];
		if (my @map = $self->field_map) {
			my $hash = { map { $_ => shift @fields } @map };
			delete $hash->{null};
			$addition = $hash;
		} 
		eval { $self->call_trigger(after_processing => $addition) };

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 1.347 second using v1.00-cache-2.02-grep-82fe00e-cpan-d29e8ade9f55 )