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

Hello Kind and Wise Monks:

I have a requirement to produce a CSV file containing security identifiers. Using Text::CSV_XS the task has proceeded very smoothly. However, an issue has surfaced that puzzles me.
Please look at the following:
ISIN: **US4663671091** CUSIP: **466367109** BBCode:**JBX UN** SEDOL: **2344922** Ticker: **JBX** SecType: **Equity** SecDesc: **JACK IN THE BOX INC** SecCurr: **USD** US4663671091 ISIN 466367109 CUSIP 05 30 CSV String: US4663671091,ISIN,466367109,CUSIP,,,05,30,,,,"JACK IN THE +BOX INC",,,USD,,, End-Of-Record

Notice the line before End-Of_Record, JACK IN THE BOX INC is in quotes. Why oh Why would Text::CSV do this? I did nothing different with this string?
My code is below.

Many thanks for considering my problem.

kd

while($db->FetchRow()){ undef %rowData; %rowData = $db->DataHash(); print " ISIN: **". $rowData{ "ISIN"} . "**\n" ; $ISIN = $rowData{ "ISIN"} ; print "CUSIP: **". $rowData{ "CUSIP"} . "**\n" ; $CUSIP = $rowData{ "CUSIP"} ; print "BBCode:**". $rowData{ "Bloomberg_Code"} . "**\n" ; $BBCode = $rowData{ "Bloomberg_Code"} ; print "SEDOL: **". $rowData{ "Sedol" } . "**\n" ; $SEDOL = $rowData{ "Sedol" }; print "Ticker: **". $rowData{ "Ticker" } . "**\n" ; $Ticker = $rowData{ "Ticker" } ; print "SecType: **" . $rowData{ "Security_Type" } . "**\n" ; $SecurityType = $rowData{ "Security_Type" } ; print "SecDesc: **" . $rowData{ "Security_Description" } . "** +\n" ; $SecurityDesc = $rowData{ "Security_Description" } ; print "SecCurr: **" . $rowData{ "Security_Issue_Ccy" } . "**\n +" ; $SecIssueCCY = $rowData{ "Security_Issue_Ccy" } ; #** ** ** ** ** ** ** # Set the Primary Identifier if ( defined($ISIN) ) { $PIdentifier = $ISIN; $PIdentifierType = 'ISIN'; $ISIN = undef; } elsif ( defined($CUSIP)) { $PIdentifier = $CUSIP; $PIdentifierType = 'CUSIP'; $CUSIP = undef; } elsif (defined($SEDOL)) { $PIdentifier = $SEDOL; $PIdentifierType = 'SEDOL'; $SEDOL = undef; } elsif (defined($BBCode)) { $PIdentifier = $BBCode; $PIdentifierType = 'Bloomberg'; $BBCode = undef; } else { $PIdentifier = $Ticker; $PIdentifierType = 'Ticker'; $Ticker = undef; } #** ** ** ** ** ** ** # Set the secondary Identifier if ( defined($ISIN) ) { $PIdentifier2 = $ISIN; $PIdentifierType2 = 'ISIN'; $ISIN = undef; } elsif ( defined($CUSIP)) { $PIdentifier2 = $CUSIP; $PIdentifierType2 = 'CUSIP'; $CUSIP = undef; } elsif (defined($SEDOL)) { $PIdentifier2 = $SEDOL; $PIdentifierType2 = 'SEDOL'; $SEDOL = undef; } elsif (defined($BBCode)) { $PIdentifier2 = $BBCode; $PIdentifierType2 = 'Bloomberg'; $BBCode = undef; } else { $PIdentifier2 = $Ticker; $PIdentifierType2 = 'Ticker'; $Ticker = undef; } print $PIdentifier . " " . $PIdentifierType , "\n"; print $PIdentifier2 . " " . $PIdentifierType2 , "\n"; #** ** ** ** ** ** ** # Set Class and Sub Class if ('CASH' eq uc($SecurityType) ) { $class = '07'; $subClass = '60'; } elsif ('BOND' eq uc($SecurityType) ) { $class = '01'; $subClass = '03'; } elsif ('EQUITY' eq uc($SecurityType) ) { $class = '05'; $subClass = '30'; } elsif ('EQUITYFUTURE' eq uc($SecurityType) ) { $class = '02'; $subClass = '30'; } elsif ('EQUITYOPTION' eq uc($SecurityType) ) { $class = '03'; $subClass = '30'; } elsif ('PREFEQUITY' eq uc($SecurityType) ) { $class = '05'; $subClass = '31'; } else { $class = '00'; $subClass = '00'; } print $class . " " . $subClass , "\n"; $status = $csv->combine( ($PIdentifier , $PIdentifierType , $PId +entifier2 , $PIdentifierType2 , "", "", $class , $subClass ,"", "","", $SecurityDesc , + "", "", $SecIssueCCY , "", "", "" ) ) ; print "CSV String: " . $csv->string(); print "\nEnd-Of-Record \n\n" ; # new line } # ** ** **

Replies are listed 'Best First'.
Re: Text::CSV_XS issue
by WoodyWeaver (Monk) on Jan 09, 2008 at 21:07 UTC
    > Why oh Why would Text::CSV do this? I did nothing different with this string?

    Because its a feature?

    Look at the parameters on new:

    quote_char

    The char used for quoting fields containing blanks, by default the double quote character ("). A value of undef suppresses quote chars. (For simple cases only).
    The CSV specification, as defined in RFC4180, is somewhat contentious, particularly with regard to quoting and spaces. It appears that your code is doing something "reasonable", and not quoting when the param doesn't contain a space, and quoting when it does.
Re: Text::CSV_XS issue
by Anonymous Monk on Jan 09, 2008 at 21:00 UTC

    Hi

    Just a guess, it seems to be the only string
    with spaces included in the CSV string.

    Worth a test?

    J.C.

      Bingo. I found a description with no spaces and indeed there are no quotes.
      How do I turn off this behavior?

      kd

        You can turn off the quotes as I described in my previous post, but I sincerely doubt if that is wise, as you're breaking with standards:

        my $csv = Text::CSV_XS->new ({ quote_char => undef });

        And having no quote character might break any standard-compliant parsers.


        Enjoy, Have FUN! H.Merijn
Re: Text::CSV_XS issue
by CountZero (Bishop) on Jan 10, 2008 at 06:29 UTC
    Why are you worried about the fact that some fields are being quoted? Does it cause problems at a later stage in processing this data? I would be happy that Text::CSV_XS has chosen the safer route.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Well the quotes are of concern because I am working off a requirement. Meaning I am required to provide the data in a specified format. It does not have quotes around any strings

      But believe me having worked with many CSV files, there are many many flavors of CSV.
      many thanks to all for their assistance.

      kd
Re: Text::CSV_XS issue
by Tux (Canon) on Jan 09, 2008 at 20:54 UTC

    I cannot tell without seeing your constructor. How did you initialize $csv?


    Enjoy, Have FUN! H.Merijn
      not thing interesting here. straight out of the doc's use Text::CSV_XS; # ** ** ** ** ** ** # Create the CSV object $csv = Text::CSV_XS->new();

        Well, it does matter:

        $ perl -MText::CSV_XS -wle'my$csv=Text::CSV_XS->new();' \ > -e'$csv->combine(1,"foo","bar baz");' \ > -e'print $csv->string' 1,foo,"bar baz" $ perl -MText::CSV_XS -wle'my$csv=Text::CSV_XS->new({quote_char=>undef +});' \ > -e'$csv->combine(1,"foo","bar baz");' \ > -e'print $csv->string' 1,foo,bar baz $ perl -MText::CSV_XS -wle'my$csv=Text::CSV_XS->new({always_quote=>1}) +;' \ > -e'$csv->combine(1,"foo","bar baz");' \ > -e'print $csv->string' "1","foo","bar baz" $

        Enjoy, Have FUN! H.Merijn