Here's a simple CSV tester that sees whether a given CSV module can parse and produce CSV that contains some of the more common features. I've also included a sample MyCSV.pm that uses Text::CSV_XS. The basic idea of the test is that you start with a CSV string, parse that into a table of rows and columns as an AoA; test the AoA to see if it has the right values in the right places; then turn the AoA back into a CSV string (i.e. turn the table's rows and columns into CSV) and test it against the original string.

The example should produce a table of two rows with three columns each. The second column of the first row contains embedded quotes, commas, and newlines. The second column of the second row is NULL (i.e. undef).

update : added tests for rows and columns

# csv_test.pl
#!/usr/bin/perl -w use strict; use Test::More tests => 5; use MyCSV; my $old_csv = qq{5,"a, ""b""\n and c",6\n7,,8\n}; my $table = MyCSV::parse_csv( $old_csv ); my $new_csv = MyCSV::produce_csv( $table ); ok( @$table == 2 , 'correctly finds two rows' ); ok( (@{$table->[0]} == 3 and @{$table->[1]} == 3) , 'correctly finds three columns in each row' ); ok( $table->[0]->[1] eq qq{a, "b"\n and c} , 'supports parsing embedded comma, newline, quotes' ); ok( !$table->[1]->[1] , 'supports parsing NULLs' ); ok( $new_csv eq $old_csv , 'supports producing embedded comma, newline, quotes; NULLs' ); __END__
# MyCSV.pm (using Text::CSV_XS)
################ package MyCSV; ################ use Text::CSV_XS; use IO::Scalar; # parse_csv() # # receives a CSV string # returns a table of rows and column as an AoA # sub parse_csv { my($input_str)=@_; my $aoa = []; my $csv = Text::CSV_XS->new({binary=>1}); my $fh = IO::Scalar->new(\$input_str); while (my $cols = $csv->getline($fh)) { last unless @$cols; push @$aoa,$cols } return $aoa } # produce_csv() # # receives a table of rows and columns as an AoA # returns a CSV string # sub produce_csv { my($aoa)=@_; my $output_str = ''; my $csv = Text::CSV_XS->new({binary=>1}); for my $row( @$aoa ) { @$row = map {defined $_ ? $_ : ''} @$row; my $success = $csv->combine(@$row); die "Coulnd't parse '@$row'\n" unless $success; $output_str .= $csv->string . $/; } return $output_str; } 1;

In reply to Parsing and Producing CSV by jZed

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.