Translate CSV To HTML

January 15, 2013

A common format for data storage is the CSV format for comma-separated values. A common format for data presentation is HTML for browsers using tables.

Your task is to write a function that reads a file in CSV format and translates it to a table in HTML format. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

About these ads

Pages: 1 2

20 Responses to “Translate CSV To HTML”

  1. [...] today’s Programming Praxis exercise, our goal is to translate a csv file to an HTML table. Let’s get [...]

  2. My Haskell solution (see http://bonsaicode.wordpress.com/2013/01/15/programming-praxis-translate-csv-to-html/ for a version with comments):

    import Text.CSV
    import Text.Printf
    
    toTable :: [[String]] -> String
    toTable = wrap "table" unlines . wrap "tr" concat $ wrap "td" id id where
        wrap :: String -> ([b] -> String) -> (a -> b) -> [a] -> String
        wrap tag combine f xs = printf "<%s>%s</%s>" tag (combine $ map f xs) tag
    
    main :: IO ()
    main = putStrLn . either show toTable =<< parseCSVFromFile "test.csv"
    
  3. [...] Question is from here: [...]

  4. Answer in awk (here)[http://psykotedy.tumblr.com/post/40602728216/programming-praxis-convert-csv-to-html].

  5. Sorry for the sloppy comment, I don’t know the markup required for the comments here.

  6. Scott Hyndman said

    Ruby solution

    "<table><tr><td>#{csv.split("\n").join('</td></tr><tr><td>').split(',').join('</td><td>')}</td></tr></table>"
    
  7. jpv said

    Doesn’t seem anyone other than Programming Praxis dealt with quoted strings
    (which, granted, isn’t necessarily a part of ‘official’ CSV files). It does
    make the code quite a bit more interesting if you do. :)

    Anyways, here’s my short (ugly) version that doesn’t deal with quoted
    strings:

    (require racket/string)
    
    (define (csv->html csv)
      (printf "<table>\n")
      (for ([line (in-list (string-split csv "\n"))])
        (printf "  <tr>\n")
        (for ([item (in-list (string-split line ","))])
          (printf "    <td>~s</td>\n" item))
        (printf "  </tr>\n"))
      (printf "</table>\n"))
    

    And here’s a longer (more awesome!) version that correctly deals with
    quotes and translates what it can to Scheme values (numbers, symbols,
    #t/#f, etc): blog post

  8. [...] post is a Python solution to a programming challenge from Programming Praxis. The challenge is to read a csv file and convert it into an html [...]

  9. Meke said

    Here’s a solution in PHP:

    <?php
    define("DIRECTORY", "./");
    if (file_exists(DIRECTORY."x.txt")) {
    $xfile = fopen(DIRECTORY."x.txt", "r");
    $xcontent = fgetcsv($xfile);
    echo "
    “;
    foreach ($xcontent as $xentry) {
    echo “”.$xentry.””;
    }
    echo ”

    “;
    } else die(“The file does not exist.”);
    ?>

  10. mekesia said

    Quotation marks delineated with a q:

    <?php
    define("DIRECTORY", "./");
    if (file_exists(DIRECTORY."x.txt")) {
    $xfile = fopen(DIRECTORY."x.txt", "r");
    $xcontent = fgetcsv($xfile);
    echo q
    q;
    foreach ($xcontent as $xentry) {
    echo qq.$xentry.qq;
    }
    echo q

    q;
    } else die(“The file does not exist.”);
    ?>

  11. mekesia said

    Third time is NOT a charm… :/

  12. Praveen S M said

    CSV To HTML

  13. Praveen S M said

    Using JSP

    CSV To HTML

  14. Mike said

    Python 3.3 solution. Uses the standard library csv to read the file and elementtree to build the table as an xml document. The tostring method takes care of properly escaping characters like <, if any, in the file.

    import csv
    import xml.etree.ElementTree as et

    def csv2html(filelike_obj, id_=None):

    table = et.Element(‘table’, {‘id’:id_} if id_ else {})

    for n, line in enumerate(csv.reader(filelike_obj)):
    row = et.SubElement(table, ‘tr’)
    if n&1: row.set(‘class’, ‘odd’)

    for item in line:
    col = et.SubElement(row, ‘td’)
    col.text = item

    return et.tostring(table, method=’html’).decode()

  15. Mike said

    Not sure what happened to the formatting above.

    import csv
    import xml.etree.ElementTree as et
    
    def csv2html(filelike_obj, id_=None):
    
        table = et.Element('table', {'id':id_} if id_ else {})
    
        for n, line in enumerate(csv.reader(filelike_obj)):
            row = et.SubElement(table, 'tr')
            if n&1: row.set('class', 'odd')
            
            for item in line:
                col = et.SubElement(row, 'td')
                col.text = item
    
        return et.tostring(table, method='html').decode()
    
    
  16. dead_ant said

    C#:

    static string Csv2Html(string filePath) {
                    return "<table>" + 
                        new StreamReader(filePath)
                            .ReadToEnd()
                            .Split('\n')
                            .Aggregate(string.Empty, (body, record) => body + "<tr>" + 
                                record.Trim()
                                .Split(',').Aggregate(string.Empty, (w, s) => w  + "<td>" + s + "</td>")
                               + "</tr>\n") + "</table>";
                }
    
  17. erdalkiran said

    C#:

    namespace CsvToHtml
    {
        using System.IO;
        using System.Text;
        using System.Web;
    
        internal class Program
        {
            #region Methods
    
            private static void Main(string[] args)
            {
                var csv = ReadData(args[0]);
                var htmlEncoded = HttpUtility.HtmlEncode(csv);
                
                var html = new StringBuilder("<table><tr><td>");
                html.Append(htmlEncoded.Replace(",", "</td></tr><tr><td>"));
                html.Append("</td></tr></table>");
            }
    
            private static string ReadData(string fileName)
            {
                var str = new StringBuilder();
    
                using (var stream = new StreamReader(fileName))
                {
                    var buffer = new char[1024];
    
                    while (!stream.EndOfStream)
                    {
                        var charactersRead = stream.ReadBlock(buffer, 0, 1024);
                        str.Append(new string(buffer, 0, charactersRead));
                    }
                }
    
                return str.ToString();
            }
    
            #endregion
        }
    }
    
  18. dead_ant said

    erdalkiran, few comments on your solution:

    1. It generates 1-column table – for every comma in the source you produce a new row in the output. Instead it should produce a cell for every comma and a row for each newline.
    2. I see no reason for manual buffered read in this case – you don’t process those chunks one by one, and in the end you still have a full raw string in memory, so why not use something like StreamReader.ReadToEnd() for simplicity?
    3. I can’t see a practical reason for using StringBuilder to store the final output here. StringBuilder might save you memory allocations and some processor cycles if you have lots of string operations, true. But you only have 2 appends. Your code will still likely force a StringBuilder to allocate memory for its internal storage, perhaps more times than it would take to allocate 3 usual immutable strings in the first place.

    Thus, I would suggest to implement your approach something like this:

    static string Csv2Html(string filePath) {
        return "<table><tr><td>" +
            new StreamReader(filePath)
                .ReadToEnd()
                .Replace("\n", "</td></tr><tr><td>") //new row for each newline
                .Replace("\r", string.Empty) //getting rid of newline leftovers, just in case
                .Replace(",", "</td><td>") //new cell for each comma
        + "</td></tr></table>";
    }
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 600 other followers

%d bloggers like this: