CSV to HTML translation

From Rosetta Code
Jump to: navigation, search
Task
CSV to HTML translation
You are encouraged to solve this task according to the task description, using any language you may know.

Consider a simplified CSV format where all rows are separated by a newline and all columns are separated by commas. No commas are allowed as field data, but the data may contain other characters and character sequences that would normally be escaped when converted to HTML

The task is to create a function that takes a string representation of the CSV data and returns a text string of an HTML table representing the CSV data. Use the following data as the CSV text to convert, and show your output.

Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!

For extra credit, optionally allow special formatting for the first row of the table as if it is the tables header row (via <thead> preferably; CSS if you must).

Contents

[edit] Ada

Works with: Ada 2005
Library: AWS

csv2html.adb:

with Ada.Strings.Fixed;
with Ada.Text_IO;
with Templates_Parser;
 
procedure Csv2Html is
use type Templates_Parser.Vector_Tag;
 
Chars : Templates_Parser.Vector_Tag;
Speeches : Templates_Parser.Vector_Tag;
 
CSV_File : Ada.Text_IO.File_Type;
begin
-- read the csv data
Ada.Text_IO.Open (File => CSV_File,
Mode => Ada.Text_IO.In_File,
Name => "data.csv");
 
-- fill the tags
while not Ada.Text_IO.End_Of_File (CSV_File) loop
declare
Whole_Line : String := Ada.Text_IO.Get_Line (CSV_File);
Comma_Pos : Natural := Ada.Strings.Fixed.Index (Whole_Line, ",");
begin
Chars := Chars & Whole_Line (Whole_Line'First .. Comma_Pos - 1);
Speeches := Speeches & Whole_Line (Comma_Pos + 1 .. Whole_Line'Last);
end;
end loop;
 
Ada.Text_IO.Close (CSV_File);
 
-- build translation table and output html
declare
Translations : constant Templates_Parser.Translate_Table :=
(1 => Templates_Parser.Assoc ("CHAR", Chars),
2 => Templates_Parser.Assoc ("SPEECH", Speeches));
begin
Ada.Text_IO.Put_Line
(Templates_Parser.Parse ("table.tmplt", Translations));
end;
end Csv2Html;

table.tmplt:

<table>
@@TABLE@@
<tr>
<td>@_WEB_ESCAPE:CHAR_@</td>
<td>@_WEB_ESCAPE:SPEECH_@</td>
</tr>
@@END_TABLE@@
</table>
Output:
<table>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.
#!/usr/local/bin/a68g --script #
 
[6]STRING rows := []STRING(
"Character,Speech",
"The multitude,The messiah! Show us the messiah!",
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>",
"The multitude,Who are you?",
"Brians mother,I'm his mother; that's who!",
"The multitude,Behold his mother! Behold his mother!"
);
 
[max abs char]STRING encoded; FOR i TO UPB encoded DO encoded[i]:=REPR i OD;
# encoded[ABS""""] := "&quot;"; optional #
encoded[ABS "&"] := "&amp;";
encoded[ABS "<"] := "&lt;";
# encoded[ABS ">"] := "&gt;"; optional #
 
OP ENCODE = (STRING s)STRING: (
STRING out := "";
FOR i TO UPB s DO out+:= encoded[ABS s[i]] OD;
out
);
 
PROC head = (STRING title)VOID: (
printf((
$"<HEAD>"l$,
$"<TITLE>"g"</TITLE>"l$, title,
$"<STYLE type=""text/css"">"l$,
$"TD {background-color:#ddddff; }"l$,
$"thead TD {background-color:#ddffdd; text-align:center; }"l$,
$"</STYLE>"l$,
$"</HEAD>"l$
))
);
 
# define HTML tags using Algol68's "reverent" block structuring #
PROC html = VOID: print(("<HTML>", new line)),
body = VOID: print(("<BODY>", new line)),
table = VOID: print(("<TABLE>", new line)),
table row = VOID: print(("<TR>")),
th = (STRING s)VOID: printf(($"<TH>"g"</TH>"$, s)),
td = (STRING s)VOID: printf(($"<TD>"g"</TD>"$, s)),
elbat row = VOID: print(("</TR>", new line)),
elbat = VOID: print(("</TABLE>", new line)),
ydob = VOID: print(("</BODY>", new line)),
lmth = VOID: print(("</HTML>", new line));
 
FILE row input; STRING row; CHAR ifs = ",";
associate(row input, row); make term(row input, ifs);
 
html;
head("CSV to HTML translation - Extra Credit");
body;
table;
FOR nr TO UPB rows DO
row := rows[nr];
table row;
on logical file end(row input, (REF FILE row input)BOOL: row end);
FOR nf DO
STRING field; get(row input,field);
(nr=1|th|td)(ENCODE field);
get(row input, space)
OD;
row end: reset(row input);
elbat row
OD;
elbat;
ydob;
lmth
Output:
<HTML>
<HEAD>
<TITLE>CSV to HTML translation - Extra Credit</TITLE>
<STYLE type="text/css">
TD {background-color:#ddddff; }
thead TD {background-color:#ddffdd; text-align:center; }
</STYLE>
</HEAD>
<BODY>
<TABLE>
<TR><TH>Character</TH><TH>Speech</TH></TR>
<TR><TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR>
<TR><TD>Brians mother</TD><TD>&lt;angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry></TD></TR>
<TR><TD>The multitude</TD><TD>Who are you?</TD></TR>
<TR><TD>Brians mother</TD><TD>I'm his mother; that's who!</TD></TR>
<TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR>
</TABLE>
</BODY>
</HTML>

[edit] AutoHotkey

Very basic implementation

CSVData = 
(
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
)
TableData := "<table>"
Loop Parse, CSVData,`n
{
TableData .= "`n <tr>"
Loop Parse, A_LoopField, CSV
TableData .= "<td>" HTMLEncode(A_LoopField) "</td>"
TableData .= "</tr>"
}
TableData .= "`n</table>"
HTMLEncode(str){
static rep := "&amp;<lt;>gt;""quot"
Loop Parse, rep,;
StringReplace, str, str, % SubStr(A_LoopField, 1, 1), % "&" . SubStr(A_LoopField, 2) . ";", All
return str
}
MsgBox % clipboard := TableData
Output:
<table>
  <tr><td>Character</td><td>Speech</td></tr>
  <tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
  <tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
  <tr><td>The multitude</td><td>Who are you?</td></tr>
  <tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
  <tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>
(note the output has been modified slightly since this webpage is html.)

[edit] AutoIt

 
Local $ascarray[4] = [34,38,60,62]
$String = "Character,Speech" & @CRLF
$String &= "The multitude,The messiah! Show us the messiah!" & @CRLF
$String &= "Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>" & @CRLF
$String &= "The multitude,Who are you?" & @CRLF
$String &= "Brians mother,I'm his mother; that's who!" & @CRLF
$String &= "The multitude,Behold his mother! Behold his mother!"
For $i = 0 To UBound($ascarray) -1
$String = Stringreplace($String, chr($ascarray[$i]), "&#"&$ascarray[$i]&";")
Next
$newstring = "<table>" & @CRLF
$crlfsplit = StringSplit($String, @CRLF, 1)
For $i = 1 To $crlfsplit[0]
If $i = 1 Then $newstring &= "<thead>" & @CRLF
$newstring &= "<tr>" & @CRLF
$komsplit = StringSplit($crlfsplit[$i], ",")
For $k = 1 To $komsplit[0]
If $i = 1 Then
$newstring &= "<th>" &$komsplit[$k] & "</th>" & @CRLF
Else
$newstring &= "<td>" &$komsplit[$k] & "</td>" & @CRLF
EndIf
Next
$newstring &= "</tr>" & @CRLF
If $i = 1 Then $newstring &= "</thead>" & @CRLF
Next
$newstring &= "</table>"
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $newstring = ' & $newstring & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
 
Output:
<table>
<thead>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
</thead>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td><angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry></td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>


[edit] ANTLR

[edit] Java

 
// Create an HTML Table from comma seperated values
// Nigel Galloway - June 2nd., 2013
grammar csv2html;
dialog : {System.out.println("<HTML><Table>");}header body+{System.out.println("</Table></HTML>");} ;
header : {System.out.println("<THEAD align=\"center\"><TR bgcolor=\"blue\">");}row{System.out.println("</TR></THEAD");};
body : {System.out.println("<TBODY><TR>");}row{System.out.println("</TR></TBODY");};
row : field ',' field '\r'? '\n';
field : Field{System.out.println("<TD>" + $Field.text.replace("<","&lt;").replace(">","&gt;") + "</TD>");};
Field : ~[,\n\r]+;
 

[edit] AWK

Works with: Gawk

Includes extra credit.
File csv2html.awk

#!/usr/bin/awk -f
BEGIN {
FS=","
print "<table>"
}
 
{
gsub(/</, "\\&lt;")
gsub(/>/, "\\&gt;")
gsub(/&/, "\\&gt;")
print "\t<tr>"
for(f = 1; f <= NF; f++) {
if(NR == 1 && header) {
printf "\t\t<th>%s</th>\n", $f
}
else printf "\t\t<td>%s</td>\n", $f
}
print "\t</tr>"
}
 
END {
print "</table>"
}
 
$ awk -f csv2html.awk input.csv
<table>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&gt;lt;angry&gt;gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&gt;lt;/angry&gt;gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

Extra credit:

$ awk -v header=1 -f csv2html.awk input.csv
<table>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&gt;lt;angry&gt;gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&gt;lt;/angry&gt;gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] BBC BASIC

      DATA "Character,Speech"
DATA "The multitude,The messiah! Show us the messiah!"
DATA "Brian's mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>"
DATA "The multitude,Who are you?"
DATA "Brian's mother,I'm his mother; that's who!"
DATA "The multitude,Behold his mother! Behold his mother!"
DATA "***"
 
*SPOOL CSVtoHTML.htm
PRINT "<HTML>"
PRINT "<HEAD>"
PRINT "</HEAD>"
PRINT "<BODY>"
PRINT "<table border=1 cellpadding =10 cellspacing=0>"
 
header% = TRUE
REPEAT
READ csv$
IF csv$ = "***" THEN EXIT REPEAT
 
IF header% PRINT "<tr><th>"; ELSE PRINT "<tr><td>";
FOR i% = 1 TO LEN(csv$)
c$ = MID$(csv$, i%, 1)
CASE c$ OF
WHEN ",": IF header% PRINT "</th><th>"; ELSE PRINT "</td><td>";
WHEN "<": PRINT "&lt;";
WHEN ">": PRINT "&gt;";
WHEN "&": PRINT "&amp;";
OTHERWISE: PRINT c$;
ENDCASE
NEXT i%
IF header% PRINT "</th></tr>" ELSE PRINT "</td></tr>"
 
header% = FALSE
UNTIL FALSE
 
PRINT "</table>"
PRINT "</BODY>"
PRINT "</HTML>"
*spool
 
SYS "ShellExecute", @hwnd%, 0, "CSVtoHTML.htm", 0, 0, 1
 
Output:
<HTML>
<HEAD>
</HEAD>
<BODY>
<table border=1 cellpadding =10 cellspacing=0>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brian's mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brian's mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>
</BODY>
</HTML>
Rendered output:

CSVHTML BBC.gif

[edit] C

#include <stdio.h>
 
const char *input =
"Character,Speech\n"
"The multitude,The messiah! Show us the messiah!\n"
"Brians mother,<angry>Now you listen here! He's not the messiah; "
"he's a very naughty boy! Now go away!</angry>\n"
"The multitude,Who are you?\n"
"Brians mother,I'm his mother; that's who!\n"
"The multitude,Behold his mother! Behold his mother!";
 
int main()
{
const char *s;
printf("<table>\n<tr><td>");
for (s = input; *s; s++) {
switch(*s) {
case '\n': printf("</td></tr>\n<tr><td>"); break;
case ',': printf("</td><td>"); break;
case '<': printf("&lt;"); break;
case '>': printf("&gt;"); break;
case '&': printf("&amp;"); break;
default: putchar(*s);
}
}
puts("</td></tr>\n</table>");
 
return 0;
}
Output:
$ gcc -Wall -W -ansi -pedantic csv.c -o csv
$ ./csv
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] C++

#include <string>
#include <boost/regex.hpp>
#include <iostream>
 
std::string csvToHTML( const std::string & ) ;
 
int main( ) {
std::string text = "Character,Speech\n"
"The multitude,The messiah! Show us the messiah!\n"
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>\n"
"The multitude,Who are you?\n"
"Brians mother,I'm his mother; that's who!\n"
"The multitude,Behold his mother! Behold his mother!\n" ;
std::cout << csvToHTML( text ) ;
return 0 ;
}
 
std::string csvToHTML( const std::string & csvtext ) {
//the order of the regexes and the replacements is decisive!
std::string regexes[ 5 ] = { "<" , ">" , "^(.+?)\\b" , "," , "\n" } ;
const char* replacements [ 5 ] = { "&lt;" , "&gt;" , " <TR><TD>$1" , "</TD><TD>", "</TD></TR>\n" } ;
boost::regex e1( regexes[ 0 ] ) ;
std::string tabletext = boost::regex_replace( csvtext , e1 ,
replacements[ 0 ] , boost::match_default | boost::format_all ) ;
for ( int i = 1 ; i < 5 ; i++ ) {
e1.assign( regexes[ i ] ) ;
tabletext = boost::regex_replace( tabletext , e1 , replacements[ i ] , boost::match_default | boost::format_all ) ;
}
tabletext = std::string( "<TABLE>\n" ) + tabletext ;
tabletext.append( "</TABLE>\n" ) ;
return tabletext ;
}
Output:
 
<TABLE>
<TR><TD>Character</TD><TD>Speech</TD></TR>
<TR><TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR>
<TR><TD>Brians mother</TD><TD>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</TD></TR>
<TR><TD>The multitude</TD><TD>Who are you?</TD></TR>
<TR><TD>Brians mother</TD><TD>I'm his mother; that's who!</TD></TR>
<TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR>
</TABLE>
 

[edit] C#

[edit] Simple Solution

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
 
class Program
{
private static string ConvertCsvToHtmlTable(string csvText)
{
//split the CSV, assume no commas or line breaks in text
List<List<string>> splitString = new List<List<string>>();
List<string> lineSplit = csvText.Split('\n').ToList();
foreach (string line in lineSplit)
{
splitString.Add(line.Split(',').ToList());
}
 
//encode text safely, and create table
string tableResult = "<table>";
foreach(List<string> splitLine in splitString)
{
tableResult += "<tr>";
foreach(string splitText in splitLine)
{
tableResult += "<td>" + WebUtility.HtmlEncode(splitText) + "</td>";
}
tableResult += "</tr>";
}
tableResult += "</table>";
return tableResult;
}
}
 
Output:
when using the text suggested:
 
<table><tr><td>Character</td><td>Speech</td></tr><tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr><tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&#39;s not the messiah; he&#39;s a very naughty boy! Now go away!&lt;/angry&gt;</td></tr><tr><td>The multitude</td><td>Who are you?</td></tr><tr><td>Brians mother</td><td>I&#39;m his mother; that&#39;s who!</td></tr><tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr></table>
 

[edit] Extra Credit Solution

using System;
using System.Linq;
using System.Net;
 
namespace CsvToHtml
{
class Program
{
static void Main(string[] args)
{
string csv =
@"Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"
;
 
Console.Write(ConvertCsvToHtmlTable(csv, true));
}
 
private static string ConvertCsvToHtmlTable(string csvText, bool formatHeaders)
{
var rows =
(from text in csvText.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) /* Split the string by newline,
* removing any empty rows. */

select text.Split(',')).ToArray(); // Split each row by comma.
 
string output = "<table>"; // Initialize the output with the value of "<table>".
 
for (int index = 0; index < rows.Length; index++) // Iterate through each row.
{
var row = rows[index];
var tag = (index == 0 && formatHeaders) ? "th" : "td"; /* Check if this is the first row, and if to format headers.
* If so, then set the tags as table headers.
* Otherwise, set the tags as table data. */

 
output += "\r\n\t<tr>"; // Add table row tag to output string.
 
// Add escaped cell data with proper tags to output string for each cell in row.
output = row.Aggregate(output,
(current, cell) =>
current +
string.Format("\r\n\t\t<{0}>{1}</{0}>", tag, WebUtility.HtmlEncode(cell)));
 
output += "\r\n\t</tr>"; // Add closing table row tag to output string.
}
 
output += "\r\n</table>"; // Add closing table tag to output string.
 
return output;
}
}
}
Sample HTML Output:
<table>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He&#39;s not the messiah; he&#39;s a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I&#39;m his mother; that&#39;s who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] CoffeeScript

Works with: node.js
String::__defineGetter__ 'escaped', () ->
this.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;') // rosettacode doesn't like "
 
text = '''
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
'''

 
lines = (line.split ',' for line in text.split /[\n\r]+/g)
 
header = lines.shift()
 
console.log """
<table cellspacing="0">
<thead>
<th scope="col">#{header[0]}</th>
<th scope="col">#{header[1]}</th>
</thead>
<tbody>
"""

 
for line in lines
[character, speech] = line
console.log """
<th scope="row">#{character}</th>
<td>#{speech.escaped}</td>
"""

 
console.log """
</tbody>
</table>
"""
Output:
<table cellspacing="0">
<thead>
<th scope="col">Character</th>
<th scope="col">Speech</th>
</thead>
<tbody>
<th scope="row">The multitude</th>
<td>The messiah! Show us the messiah!</td>
<th scope="row">Brians mother</th>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
<th scope="row">The multitude</th>
<td>Who are you?</td>
<th scope="row">Brians mother</th>
<td>I'm his mother; that's who!</td>
<th scope="row">The multitude</th>
<td>Behold his mother! Behold his mother!</td>
</tbody>
</table>


[edit] Common Lisp

(defvar *csv* "Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"
)
 
(defun split-string (string delim-char)
(let ((result '()))
(do* ((start 0 (1+ end))
(end (position delim-char string)
(position delim-char string :start start)))
((not end) (reverse (cons (subseq string start) result)))
(push (subseq string start end) result))))
 
;;; HTML escape code modified from:
;;; http://www.gigamonkeys.com/book/practical-an-html-generation-library-the-interpreter.html
 
(defun escape-char (char)
(case char
(#\& "&amp;")
(#\< "&lt;")
(#\> "&gt;")
(t (format nil "&#~d;" (char-code char)))))
 
(defun escape (in)
(let ((to-escape "<>&"))
(flet ((needs-escape-p (char) (find char to-escape)))
(with-output-to-string (out)
(loop for start = 0 then (1+ pos)
for pos = (position-if #'needs-escape-p in :start start)
do (write-sequence in out :start start :end pos)
when pos do (write-sequence (escape-char (char in pos)) out)
while pos)))))
 
(defun html-row (values headerp)
(let ((tag (if headerp "th" "td")))
(with-output-to-string (out)
(write-string "<tr>" out)
(dolist (val values)
(format out "<~A>~A</~A>" tag (escape val) tag))
(write-string "</tr>" out))))
 
(defun csv->html (csv)
(let* ((lines (split-string csv #\Newline))
(cols (split-string (first lines) #\,))
(rows (mapcar (lambda (row) (split-string row #\,)) (rest lines))))
(with-output-to-string (html)
(format html "<table>~C" #\Newline)
(format html "~C~A~C" #\Tab (html-row cols t) #\Newline)
(dolist (row rows)
(format html "~C~A~C" #\Tab (html-row row nil) #\Newline))
(write-string "</table>" html))))
CL-USER> (csv->html *csv*)
Output:
<table>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] D

Translation of: C
void main() {
import std.stdio;
 
immutable input =
"Character,Speech\n" ~
"The multitude,The messiah! Show us the messiah!\n" ~
"Brians mother,<angry>Now you listen here! He's not the messiah; " ~
"he's a very naughty boy! Now go away!</angry>\n" ~
"The multitude,Who are you?\n" ~
"Brians mother,I'm his mother; that's who!\n" ~
"The multitude,Behold his mother! Behold his mother!";
 
"<html>\n<head><meta charset=\"utf-8\"></head>\n<body>\n\n".write;
"<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n<thead>\n <tr><td>".write;
 
bool theadDone = false;
 
foreach (immutable c; input) {
switch(c) {
case '\n':
if (theadDone) {
"</td></tr>\n <tr><td>".write;
} else {
"</td></tr>\n</thead>\n<tbody>\n <tr><td>".write;
theadDone = true;
}
break;
case ',': "</td><td>".write; break;
case '<': "&lt;".write; break;
case '>': "&gt;".write; break;
case '&': "&amp;".write; break;
default: c.write; break;
}
}
 
"</td></tr>\n</tbody>\n</table>\n\n</body></html>".write;
}
Output:
<html>
<head><meta charset="utf-8"></head>
<body>
 
<table border="1" cellpadding="5" cellspacing="0">
<thead>
<tr><td>Character</td><td>Speech</td></tr>
</thead>
<tbody>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</tbody>
</table>
 
</body>
</html>

[edit] Delphi

This solution solves both the basic and extra credit tasks.

program csv2html;
 
{$APPTYPE CONSOLE}
 
uses
SysUtils,
Classes;
 
const
// Carriage Return/Line Feed
CRLF = #13#10;
 
// The CSV data
csvData =
'Character,Speech'+CRLF+
'The multitude,The messiah! Show us the messiah!'+CRLF+
'Brians mother,<angry>Now you listen here! He''s not the messiah; he''s a very naughty boy! Now go away!</angry>'+CRLF+
'The multitude,Who are you?'+CRLF+
'Brians mother,I''m his mother; that''s who!'+CRLF+
'The multitude,Behold his mother! Behold his mother!';
 
// HTML header
htmlHead =
'<!DOCTYPE html'+CRLF+
'PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'+CRLF+
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'+CRLF+
'<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">'+CRLF+
'<head>'+CRLF+
'<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />'+CRLF+
'<title>CSV-to-HTML Conversion</title>'+CRLF+
'<style type="text/css">'+CRLF+
'body {font-family:verdana,helvetica,sans-serif;font-size:100%}'+CRLF+
'table {width:70%;border:0;font-size:80%;margin:auto}'+CRLF+
'th,td {padding:4px}'+CRLF+
'th {text-align:left;background-color:#eee}'+CRLF+
'th.c {width:15%}'+CRLF+
'td.c {width:15%}'+CRLF+
'</style>'+CRLF+
'</head>'+CRLF+
'<body>'+CRLF;
 
// HTML footer
htmlFoot =
'</body>'+CRLF+
'</html>';
 
{ Function to split a string into a list using a given delimiter }
procedure SplitString(S, Delim: string; Rslt: TStrings);
var
i: integer;
fld: string;
begin
fld := '';
 
for i := Length(S) downto 1 do
begin
if S[i] = Delim then
begin
Rslt.Insert(0,fld);
fld := '';
end
else
fld := S[i]+fld;
end;
 
if (fld <> '') then
Rslt.Insert(0,fld);
end;
 
{ Simple CSV parser with option to specify that the first row is a header row }
procedure ParseCSV(const csvIn: string; htmlOut: TStrings; FirstRowIsHeader: Boolean = True);
const
rowstart = '<tr><td class="c">';
rowend = '</td></tr>';
cellendstart = '</td><td class="s">';
hcellendstart = '</th><th class="s">';
hrowstart = '<tr><th class="c">';
hrowend = '</th></tr>';
var
tmp,pieces: TStrings;
i: Integer;
begin
// HTML header
htmlOut.Text := htmlHead + CRLF + CRLF;
 
// Start the HTML table
htmlOut.Text := htmlOut.Text + '<table summary="csv2table conversion">' + CRLF;
 
// Create stringlist
tmp := TStringList.Create;
try
// Assign CSV data to stringlist and fix occurences of '<' and '>'
tmp.Text := StringReplace(csvIn,'<','&lt;',[rfReplaceAll]);
tmp.Text := StringReplace(tmp.Text,'>','&gt;',[rfReplaceAll]);
 
// Create stringlist to hold the parts of the split data
pieces := TStringList.Create;
try
 
// Loop through the CSV rows
for i := 0 to Pred(tmp.Count) do
begin
// Split the current row
SplitString(tmp[i],',',pieces);
 
// Check if first row and FirstRowIsHeader flag set
if (i = 0) and FirstRowIsHeader then
 
// Render HTML
htmlOut.Text := htmlOut.Text + hrowstart + pieces[0] + hcellendstart + pieces[1] + hrowend + CRLF
else
htmlOut.Text := htmlOut.Text + rowstart + pieces[0] + cellendstart + pieces[1] + rowend + CRLF;
 
end;
 
// Finish the HTML table and end the HTML page
htmlOut.Text := htmlOut.Text + '</table>' + CRLF + htmlFoot;
 
finally
pieces.Free;
end;
 
finally
tmp.Free;
end;
end;
 
var
HTML: TStrings;
 
begin
// Create stringlist to hold HTML output
HTML := TStringList.Create;
try
Writeln('Basic:');
Writeln('');
 
// Load and parse the CSV data
ParseCSV(csvData,HTML,False);
 
// Output the HTML to the console
Writeln(HTML.Text);
 
// Save the HTML to a file (in application's folder)
HTML.SaveToFile('csv2html_basic.html');
 
Writeln('');
Writeln('=====================================');
Writeln('');
 
HTML.Clear;
 
Writeln('Extra Credit:');
Writeln('');
 
// Load and parse the CSV data
ParseCSV(csvData,HTML,True);
 
// Output the HTML to the console
Writeln(HTML.Text);
 
// Save the HTML to a file (in application's folder)
HTML.SaveToFile('csv2html_extra.html');
Writeln('');
Writeln('=====================================');
 
finally
HTML.Free;
end;
 
// Keep console window open
Readln;
end.
Basic output:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<title>CSV-to-HTML Conversion</title>
<style type="text/css">
body {font-family:verdana,helvetica,sans-serif;font-size:100%}
table {width:70%;border:0;font-size:80%;margin:auto}
th,td {padding:4px}
th {text-align:left;background-color:#eee}
th.c {width:15%}
td.c {width:15%}
</style>
</head>
<body>
 
 
<table summary="csv2table conversion">
<tr><td class="c">Character</td><td class="s">Speech</td></tr>
<tr><td class="c">The multitude</td><td class="s">The messiah! Show us the messiah!</td></tr>
<tr><td class="c">Brians mother</td><td class="s">&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td class="c">The multitude</td><td class="s">Who are you?</td></tr>
<tr><td class="c">Brians mother</td><td class="s">I'm his mother; that's who!</td></tr>
<tr><td class="c">The multitude</td><td class="s">Behold his mother! Behold his mother!</td></tr>
</table>
</body>
</html>
Extra credit output:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<title>CSV-to-HTML Conversion</title>
<style type="text/css">
body {font-family:verdana,helvetica,sans-serif;font-size:100%}
table {width:70%;border:0;font-size:80%;margin:auto}
th,td {padding:4px}
th {text-align:left;background-color:#eee}
th.c {width:15%}
td.c {width:15%}
</style>
</head>
<body>
 
 
<table summary="csv2table conversion">
<tr><th class="c">Character</th><th class="s">Speech</th></tr>
<tr><td class="c">The multitude</td><td class="s">The messiah! Show us the messiah!</td></tr>
<tr><td class="c">Brians mother</td><td class="s">&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td class="c">The multitude</td><td class="s">Who are you?</td></tr>
<tr><td class="c">Brians mother</td><td class="s">I'm his mother; that's who!</td></tr>
<tr><td class="c">The multitude</td><td class="s">Behold his mother! Behold his mother!</td></tr>
</table>
</body>
</html>

[edit] Erlang

Using functions from Create_an_HTML_table

 
-module( csv_to_html ).
 
-export( [table_translation/1, task/0] ).
 
table_translation( CSV ) ->
[Headers | Contents] = [string:tokens(X, ",") || X <- string:tokens( CSV, "\n")],
Table = create_html_table:html_table( [{border, "1"}, {cellpadding, "10"}], Headers, Contents ),
create_html_table:external_format( Table ).
 
task() -> table_translation( csv() ).
 
 
 
csv() ->
"Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"
.
 
Output:
CharacterSpeech
The multitudeThe messiah! Show us the messiah!
Brians mother<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitudeWho are you?
Brians motherI'm his mother; that's who!
The multitudeBehold his mother! Behold his mother!

[edit] Euphoria

Translation of: C
Works with: Euphoria version 4.*
constant input = "Character,Speech\n" &
"The multitude,The messiah! Show us the messiah!\n" &
"Brians mother,<angry>Now you listen here! He's not the messiah; " &
"he's a very naughty boy! Now go away!</angry>\n" &
"The multitude,Who are you?\n" &
"Brians mother,I'm his mother; that's who!\n" &
"The multitude,Behold his mother! Behold his mother!"
 
puts(1,"<table>\n<tr><td>")
for i = 1 to length(input) do
switch input[i] do
case '\n' then puts(1,"</td></tr>\n<tr><td>")
case ',' then puts(1,"</td><td>")
case '<' then puts(1,"&lt;")
case '>' then puts(1,"&gt;")
case '&' then puts(1,"&amp;")
case else puts(1,input[i])
end switch
end for
puts(1,"</td></tr>\n</table>")
Output:
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td><angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry></td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] F#

Use .NET XmlWriter. Stylesheet styling is applied only when command line option -h ist given.

open System
open System.Text
open System.Xml
 
let data = """
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
"
""
 
let csv =
Array.map
(fun (line : string) -> line.Split(','))
(data.Trim().Split([|'\n';'\r'|],StringSplitOptions.RemoveEmptyEntries))
 
 
[<EntryPoint>]
let main argv =
let style = argv.Length > 0 && argv.[0] = "-h"
Console.OutputEncoding <- UTF8Encoding()
let xs = XmlWriterSettings()
xs.Indent <- true // be friendly to humans
use x = XmlWriter.Create(Console.Out, xs)
x.WriteStartDocument()
x.WriteDocType("HTML", null, null, null) // HTML5
x.WriteStartElement("html")
x.WriteStartElement("head")
x.WriteElementString("title", "Rosettacode - CSV to HTML translation")
if style then
x.WriteStartElement("style"); x.WriteAttributeString("type", "text/css")
x.WriteString("""
table { border-collapse: collapse; }
td, th { border: 1px solid black; padding: .25em}
th { background-color: #EEE; }
tbody th { font-weight: normal; font-size: 85%; }
"
"")
x.WriteEndElement() // style
x.WriteEndElement() // head
x.WriteStartElement("body")
x.WriteStartElement("table")
x.WriteStartElement("thead"); x.WriteStartElement("tr")
for part in csv.[0] do x.WriteElementString("th", part)
x.WriteEndElement(); x.WriteEndElement() // tr thead
x.WriteStartElement("tbody")
for line in csv.[1..] do
x.WriteStartElement("tr")
x.WriteElementString("th", line.[0])
x.WriteElementString("td", line.[1])
x.WriteEndElement() // tr
x.Close()
0
Output:
(stylesheet version)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE HTML >
<html>
<head>
<title>Rosettacode - CSV to HTML translation</title>
<style type="text/css">
table { border-collapse: collapse; }
td, th { border: 1px solid black; padding: .25em}
th { background-color: #EEE; }
tbody th { font-weight: normal; font-size: 85%; }
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
</thead>
<tbody>
<tr>
<th>The multitude</th>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<th>Brians mother</th>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<th>The multitude</th>
<td>Who are you?</td>
</tr>
<tr>
<th>Brians mother</th>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<th>The multitude</th>
<td>Behold his mother! Behold his mother!</td>
</tr>
</tbody>
</table>
</body>
</html>

[edit] Go

package main
 
import (
"bytes"
"encoding/csv"
"fmt"
"html/template"
)
 
var c = `Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!`

 
func main() {
if h, err := csvToHtml(c); err != nil {
fmt.Println(err)
} else {
fmt.Print(h)
}
}
 
func csvToHtml(c string) (string, error) {
data, err := csv.NewReader(bytes.NewBufferString(c)).ReadAll()
if err != nil {
return "", err
}
var b bytes.Buffer
err = template.Must(template.New("").Parse(`<table>
{{range .}} <tr>{{range .}}<td>{{.}}</td>{{end}}</tr>
{{end}}</table>
`
)).Execute(&b, data)
return b.String(), err
}

Extra credit version accepts -h command line option to do the special formatting for the heading line.

package main
 
import (
"bytes"
"encoding/csv"
"flag"
"fmt"
"html/template"
)
 
var csvStr = `Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!`

 
func main() {
headings := flag.Bool("h", false, "format first row as column headings")
flag.Parse()
if html, err := csvToHtml(csvStr, *headings); err != nil {
fmt.Println(err)
} else {
fmt.Print(html)
}
}
 
func csvToHtml(csvStr string, headings bool) (string, error) {
data, err := csv.NewReader(bytes.NewBufferString(csvStr)).ReadAll()
if err != nil {
return "", err
}
tStr := tPlain
if headings {
tStr = tHeadings
}
var b bytes.Buffer
err = template.Must(template.New("").Parse(tStr)).Execute(&b, data)
return b.String(), err
}
 
const (
tPlain = `<table>
{{range .}} <tr>{{range .}}<td>{{.}}</td>{{end}}</tr>
{{end}}</table>
`

tHeadings = `<table>{{if .}}
{{range $x, $e := .}}{{if $x}}
<tr>{{range .}}<td>{{.}}</td>{{end}}</tr>{{else}} <thead>
<tr>{{range .}}<th>{{.}}</th>{{end}}</tr>
</thead>
<tbody>{{end}}{{end}}
</tbody>{{end}}
</table>
`

)
Output:

Extra credit version with -h

<table>
<thead>
<tr><th>Character</th><th>Speech</th></tr>
</thead>
<tbody>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&#39;s not the messiah; he&#39;s a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I&#39;m his mother; that&#39;s who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</tbody>
</table>

Basic version, or extra credit version without -h

<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&#39;s not the messiah; he&#39;s a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I&#39;m his mother; that&#39;s who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Groovy

[edit] Solution #1: Nested GStrings

Brute force solution using nested GStrings. It solves both the basic and extra credit tasks.

def formatCell = { cell ->
"<td>${cell.replaceAll('&','&amp;').replaceAll('<','&lt;')}</td>"
}
 
def formatRow = { row ->
"""<tr>${row.split(',').collect { cell -> formatCell(cell) }.join('')}</tr>
"""

}
 
def formatTable = { csv, header=false ->
def rows = csv.split('\n').collect { row -> formatRow(row) }
header \
? """
<table>
<thead>
${rows[0]}</thead>
<tbody>
${rows[1..-1].join('')}</tbody>
</table>
"""
\
 : """
<table>
${rows.join('')}</table>
"""

}
 
def formatPage = { title, csv, header=false ->
"""<html>
<head>
<title>${title}</title>
<style type="text/css">
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head>
<body>${formatTable(csv, header)}</body>
</html>"""

}

Test:

def csv = '''Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!'''

 
println 'Basic:'
println '-----------------------------------------'
println (formatPage('Basic', csv))
println '-----------------------------------------'
println()
println()
println 'Extra Credit:'
println '-----------------------------------------'
println (formatPage('Extra Credit', csv, true))
println '-----------------------------------------'
Basic output:
<html>
<head>
<title>Basic</title>
<style type="text/css">
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head>
<body>
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry></td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>
</body>
</html>

Groovy-csv-to-html-basic.jpg
Appearance as rendered in Google Chrome.

Extra Credit output:
<html>
<head>
<title>Extra Credit</title>
<style type="text/css">
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head>
<body>
<table>
<thead>
<tr><td>Character</td><td>Speech</td></tr>
</thead>
<tbody>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry></td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</tbody>
</table>
</body>
</html>

Groovy-csv-to-html-extra.jpg
Appearance as rendered in Google Chrome.

[edit] Solution #2: MarkupBuilder

A much cleaner solution using the Groovy XML MarkupBuilder class. It solves both the basic and extra credit tasks.

import groovy.xml.MarkupBuilder
 
def formatRow = { doc, row ->
doc.tr { row.each { cell -> td { mkp.yield(cell) } } }
}
 
def formatPage = { titleString, csv, header=false ->
def writer = new StringWriter()
def doc = new MarkupBuilder(writer)
def rows = csv.split('\n').collect { row -> row.split(',') }
doc.html {
head {
title (titleString)
style (type:"text/css") {
mkp.yield('''
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
'''
)
}
}
body {
table {
header && thead { formatRow(doc, rows[0]) }
header && tbody { rows[1..-1].each { formatRow(doc, it) } }
header || rows.each { formatRow(doc, it) }
}
}
}
writer.toString()
}

Test:
The interface is the same for both solutions, so we just reuse the same test as before.

Basic output:
<html>
<head>
<title>Basic</title>
<style type='text/css'>
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head>
<body>
<table>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>
</body>
</html>

The HTML for this solution looks superficially different than that from the GString solution, but the appearance as rendered in Google Chrome is identical.

Extra Credit output:

<html>
<head>
<title>Extra Credit</title>
<style type='text/css'>
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head>
<body>
<table>
<thead>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
</thead>
<tbody>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</tbody>
</table>
</body>
</html>

The HTML for this solution looks superficially different than that from the GString solution, but the appearance as rendered in Google Chrome is identical.

[edit] Haskell

Simple solution

--import Data.List.Split (splitOn)    -- if the import is available
splitOn :: Char -> String -> [String] -- otherwise
splitOn delim = foldr (\x rest ->
if x == delim then "" : rest
else (x:head rest):tail rest) [""]
 
htmlEscape :: String -> String
htmlEscape = concatMap escapeChar
where escapeChar '<' = "&lt;"
escapeChar '>' = "&gt;"
escapeChar '&' = "&amp;"
escapeChar '"' = "&quot;" --"
escapeChar c = [c]
 
toHtmlRow :: [String] -> String
toHtmlRow [] = "<tr></tr>"
toHtmlRow cols = let htmlColumns = concatMap toHtmlCol cols
in "<tr>\n" ++ htmlColumns ++ "</tr>"
where toHtmlCol x = " <td>" ++ htmlEscape x ++ "</td>\n"
 
csvToTable :: String -> String
csvToTable csv = let rows = map (splitOn ',') $ lines csv
html = unlines $ map toHtmlRow rows
in "<table>\n" ++ html ++ "</table>"
 
main = interact csvToTable

Compact version

import Data.List (unfoldr)
split p = unfoldr (\s -> case dropWhile p s of [] -> Nothing
ss -> Just $ break p ss)
 
main = interact (\csv -> "<table>\n" ++
(unlines $ map ((\cols -> "<tr>\n" ++
(concatMap (\x -> " <td>" ++ concatMap (\c ->
case c of {'<' -> "&lt;"; '>' -> "&gt;";
'&' -> "&amp;"; '"' -> "&quot;"; _ -> [c]}) x
++ "</td>\n") cols)
++ "</tr>") . split (==',')) $ lines csv) ++ "</table>")
Output
<table>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] Icon and Unicon

This solution for the extra credit works in both Icon and Unicon. The simple CSV is read from standard input and written to standard output. The presence/abscend of "-heading" in the argument list sets the variable thead to the procedure writes or a 1 (for more on this see Introduction to Icon/Unicon - Conjunction yielding different results).

procedure main(arglist)
pchar := &letters ++ &digits ++ '!?;. ' # printable chars
 
write("<TABLE>")
firstHead := (!arglist == "-heading")
tHead := write
while row := trim(read()) do {
if \firstHead then write(" <THEAD>") else tHead(" <TBODY>")
writes(" <TR><TD>")
while *row > 0 do
row ?:= ( (=",",writes("</TD><TD>")) |
writes( tab(many(pchar)) |
("&#" || ord(move(1))) ), tab(0))
write("</TD></TR>")
if (\firstHead) := &null then write(" </THEAD>\n <TBODY>")
tHead := 1
}
write(" </TBODY>")
write("</TABLE>")
end
Output:
<TABLE>
<THEAD>
<TR><TD>Character</TD><TD>Speech</TD></TR>
</THEAD>
<TBODY>
<TR><TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR>
<TR><TD>Brians mother</TD><TD>&#60angry&#62Now you listen here! He&#39s not the messiah; he&#39s a very naughty boy! Now go away!&#60&#47angry&#62</TD></TR>
<TR><TD>The multitude</TD><TD>Who are you?</TD></TR>
<TR><TD>Brians mother</TD><TD>I&#39m his mother; that&#39s who!</TD></TR>
<TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR>
</TBODY>
</TABLE>

[edit] J

Solution (extra credit)

require 'strings tables/csv'
encodeHTML=: ('&';'&amp;';'<';'&lt;';'>';'&gt;')&stringreplace
 
tag=: adverb define
'starttag endtag'=.m
(,&.>/)"1 (starttag , ,&endtag) L:0 y
)
 
markupCells=: ('<td>';'</td>') tag
markupHdrCells=: ('<th>';'</th>') tag
markupRows=: ('<tr>';'</tr>',LF) tag
markupTable=: (('<table>',LF);'</table>') tag
 
makeHTMLtablefromCSV=: verb define
0 makeHTMLtablefromCSV y NB. default left arg is 0 (no header row)
:
t=. fixcsv encodeHTML y
if. x do. t=. (markupHdrCells@{. , markupCells@}.) t
else. t=. markupCells t
end.
 ;markupTable markupRows t
)

For those interested, equivalent tacit versions of tag and makeHTMLtablefromCSV are:

tag=: adverb def '[: (,&.>/)"1 m&(0&{::@[ , 1&{::@[ ,~ ]) L:0@]'
makeHTMLtablefromCSV6=: 0&$: : ([: ; markupTable@markupRows@([ markupCells`(markupHdrCells@{. , markupCells@}.)@.[ fixcsv@encodeHTML))

Example

   CSVstrng=: noun define
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
)
1 makeHTMLtablefromCSV CSVstrng
HTML output:
<table>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Java

Solution including simple and extra credit version

for simple solution  : java -cp . Csv2Html < text.csv

for extended solution: java -cp . Csv2Html header < text.csv

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
 
class Csv2Html {
 
public static String escapeChars(String lineIn) {
StringBuilder sb = new StringBuilder();
int lineLength = lineIn.length();
for (int i = 0; i < lineLength; i++) {
char c = lineIn.charAt(i);
switch (c) {
case '"':
sb.append("&quot;");
break;
case '&':
sb.append("&amp;");
break;
case '\'':
sb.append("&apos;");
break;
case '<':
sb.append("&lt;");
break;
case '>':
sb.append("&gt;");
break;
default: sb.append(c);
}
}
return sb.toString();
}
 
public static void tableHeader(PrintStream ps, String[] columns) {
ps.print("<tr>");
for (int i = 0; i < columns.length; i++) {
ps.print("<th>");
ps.print(columns[i]);
ps.print("</th>");
}
ps.println("</tr>");
}
 
public static void tableRow(PrintStream ps, String[] columns) {
ps.print("<tr>");
for (int i = 0; i < columns.length; i++) {
ps.print("<td>");
ps.print(columns[i]);
ps.print("</td>");
}
ps.println("</tr>");
}
 
public static void main(String[] args) throws Exception {
boolean withTableHeader = (args.length != 0);
 
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
PrintStream stdout = System.out;
 
stdout.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
stdout.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
stdout.println("<head><meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\"/>");
stdout.println("<title>Csv2Html</title>");
stdout.println("<style type=\"text/css\">");
stdout.println("body{background-color:#FFF;color:#000;font-family:OpenSans,sans-serif;font-size:10px;}");
stdout.println("table{border:0.2em solid #2F6FAB;border-collapse:collapse;}");
stdout.println("th{border:0.15em solid #2F6FAB;padding:0.5em;background-color:#E9E9E9;}");
stdout.println("td{border:0.1em solid #2F6FAB;padding:0.5em;background-color:#F9F9F9;}</style>");
stdout.println("</head><body><h1>Csv2Html</h1>");
 
stdout.println("<table>");
String stdinLine;
boolean firstLine = true;
while ((stdinLine = br.readLine()) != null) {
String[] columns = escapeChars(stdinLine).split(",");
if (withTableHeader == true && firstLine == true) {
tableHeader(stdout, columns);
firstLine = false;
} else {
tableRow(stdout, columns);
}
}
stdout.println("</table></body></html>");
}
}
 
simple solution:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
<title>Csv2Html</title>
<style type="text/css">
body{background-color:#FFF;color:#000;font-family:OpenSans,sans-serif;font-size:10px;}
table{border:0.2em solid #2F6FAB;border-collapse:collapse;}
th{border:0.15em solid #2F6FAB;padding:0.5em;background-color:#E9E9E9;}
td{border:0.1em solid #2F6FAB;padding:0.5em;background-color:#F9F9F9;}</style>
</head><body><h1>Csv2Html</h1>
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&apos;s not the messiah; he&apos;s a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I&apos;m his mother; that&apos;s who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table></body></html>
extended:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
<title>Csv2Html</title>
<style type="text/css">
body{background-color:#FFF;color:#000;font-family:OpenSans,sans-serif;font-size:10px;}
table{border:0.2em solid #2F6FAB;border-collapse:collapse;}
th{border:0.15em solid #2F6FAB;padding:0.5em;background-color:#E9E9E9;}
td{border:0.1em solid #2F6FAB;padding:0.5em;background-color:#F9F9F9;}</style>
</head><body><h1>Csv2Html</h1>
<table>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&apos;s not the messiah; he&apos;s a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I&apos;m his mother; that&apos;s who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table></body></html>

[edit] JavaScript

var csv = "Character,Speech\n" +
"The multitude,The messiah! Show us the messiah!\n" +
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>\n" +
"The multitude,Who are you?\n" +
"Brians mother,I'm his mother; that's who!\n" +
"The multitude,Behold his mother! Behold his mother!";
 
var lines = csv.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.split(/[\n\r]/)
.map(function(line) { return line.split(',')})
.map(function(row) {return '\t\t<tr><td>' + row[0] + '</td><td>' + row[1] + '</td></tr>';});
 
console.log('<table>\n\t<thead>\n' + lines[0] +
'\n\t</thead>\n\t<tbody>\n' + lines.slice(1).join('\n') +
'\t</tbody>\n</table>');
 
 
<table>
<thead>
<tr><td>Character</td><td>Speech</td></tr>
</thead>
<tbody>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</tbody>
</table>

No escaping:

This example does not show the output mentioned in the task description on this page (or a page linked to from here). Please ensure that it meets all task requirements and remove this message.
Note that phrases in task descriptions such as "print and display" and "print and show" for example, indicate that (reasonable length) output be a part of a language's solution.


//uses native DOM calls to construct HTML elements
function csv_to_table(s) {
function ce(t) { return document.createElement(t); }
function ap(t) { document.body.appendChild(t); }
var t = ce('table'), f = 0; //1;
s.split('\n').map(function(l) {
var r = ce(f ? 'tr': 'thead');
l.split(',').map(function (w) {
var c = ce(f ? 'td' : 'th');
c.textContent = w;
r.appendChild(c);
});
t.appendChild(r);
f = 1; //0;
});
//return t.innerHTML;
return t.outerHTML;
}
/*
but also with this changes is very dependent by javascript engine and/or browser version (in: IE>=9, chrome )
*/

[edit] jq

We will assume the input is in a file named csv2html.csv, and that the jq program as given below is in a file named csv2html.jqn. To simplify things, we will invoke the jq processor twice -- the first invocation simply converts the text input into a sequence of JSON strings:

jq -R . csv2html.csv | jq -r -s -f csv2html.jq  
 
def headerrow2html:
[" <thead> <tr>"]
+ (split(",") | map(" <th>\(@html)</th>"))
+ [ " </tr> </thead>" ]
;
 
def row2html:
[" <tr>"]
+ (split(",") | map(" <td>\(@html)</td>"))
+ [ " </tr>" ]
;
 
def csv2html:
def rows: reduce .[] as $row
([]; . + ($row | row2html));
["<table>"]
+ (.[0] | headerrow2html)
+ (.[1:] | rows)
+ [ "</table>"]
;
 
csv2html | .[]

[edit] Output

<table>
<thead> <tr>
<th>Character</th>
<th>Speech </th>
</tr> </thead>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah! </td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He&apos;s not the messiah; he&apos;s a very naughty boy! Now go away!&lt;/angry&gt; </td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you? </td>
</tr>
<tr>
<td>Brians mother</td>
<td>I&apos;m his mother; that&apos;s who! </td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother! </td>
</tr>
</table>

[edit] Liberty BASIC

 
newline$ ="|"
' No escape behaviour, so can't refer to '/n'.
' Generally imported csv would have separator CR LF; easily converted first if needed
 
csv$ ="Character,Speech" +newline$+_
"The multitude,The messiah! Show us the messiah!" +newline$+_
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>" +newline$+_
"The multitude,Who are you?" +newline$+_
"Brians mother,I'm his mother; that's who!" +newline$+_
"The multitude,Behold his mother! Behold his mother!"
 
print "<HTML>"
print "<HEAD>"
print "</HEAD>"
print "<BODY>"
print "<center><H1>CSV to HTML translation </H1></center>"
print "<table border=1 cellpadding =10>"
print "<tr><td>"
 
for i =1 to len( csv$)
c$ =mid$( csv$, i, 1)
select case c$
case "|": print "</td></tr>": print "<tr><td>"
case ",": print "</td><td>";
case "<": print "&"+"lt;";
case ">": print "&"+"gt;";
case "&": print "&"+"amp;";
case else: print c$;
end select
next i
 
print "</td></tr>"
print "</table>"
print "</BODY>"
print "</HTML>"
end
 
Output:
<HTML>
<HEAD>
</HEAD>
<BODY>
<center><H1>CSV to HTML translation </H1></center>
<table border=1 cellpadding =10>
<tr><td>
Character</td><td>Speech</td></tr>
<tr><td>
The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>
Brians mother</td><td><angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry></td></tr>
<tr><td>
The multitude</td><td>Who are you?</td></tr>
<tr><td>
Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>
The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>
</BODY>
</HTML>
Rendered output is available at http://www.diga.me.uk/csvhtml.gif

[edit] Lua

FS = ","            -- field separator
 
csv = [[
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
]]
 
csv = csv:gsub( "<", "&lt;" )
csv = csv:gsub( ">", "&gr;" )
 
html = { "<table>" }
for line in string.gmatch( csv, "(.-\n)" ) do
str = "<tr>"
for field in string.gmatch( line, "(.-)["..FS.."?\n?]" ) do
str = str .. "<td>" .. field .. "</td>"
end
str = str .. "</tr>"
html[#html+1] = str;
end
html[#html+1] = "</table>"
 
for _, line in pairs(html) do
print(line)
end
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gr;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gr;</td></tr>
<tr><td>The multitude</td><td>Who are you</td><td></td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Mathematica

a="Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah;he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother;that's who!
The multitude,Behold his mother! Behold his mother!";
(*Naive*)
StringJoin["<table>\n",Map[StringJoin["<tr><td>",#,"</td></tr>\n"]&,
StringSplit[StringReplace[a,{","->"</td><td>","<"->"&lt;",">"->"&gt;"}],"\n"]]
,"</table>"]
(*Extra*)
StringJoin["<table>\n",StringJoin["<tr><th>",#,"</th></tr>\n"]&[
StringSplit[StringReplace[a,{","->"</td><td>","<"->"&lt;",">"->"&gt;"}],"\n"]//First]
,Map[StringJoin["<tr><td>",#,"</td></tr>\n"]&,
StringSplit[StringReplace[a,{","->"</td><td>","<"->"&lt;",">"->"&gt;"}],"\n"]//Rest]
,"</table>"]
 
Naive:
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td><angry>Now you listen here! He's not the messiah;he's a very naughty boy! Now go away!</angry></td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother;that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>
Extra:
<table>
<tr><th>Character</td><td>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td><angry>Now you listen here! He's not the messiah;he's a very naughty boy! Now go away!</angry></td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother;that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] MATLAB

Many specialized MATLAB file IO functions are painfully slow, and with large files it is often better to use a lower-level functions such as fread. Here we use fileread, which does a little bit of error handling and calls fread, specifying the input data as text. From this text string, we can easily convert any special html characters, split it into a cell array, and print it out specifying format.

 
inputString = fileread(csvFileName);
% using multiple regular expressions to clear up special chars
htmlFriendly = regexprep(regexprep(regexprep(regexprep(inputString,...
'&','&amp;'),...
'"','&quot;'),...
'<','&lt;'),...
'>','&gt;');
% split string into cell array
tableValues = regexp(regexp(htmlFriendly,'(\r\n|\r|\n)','split')',',','split');
%%% print in html format %%%
% <Extra Credit> first line gets treated as header
fprintf(1,['<table>\n\t<tr>' sprintf('\n\t\t<th>%s</th>',tableValues{1,:}{:})])
% print remaining lines of csv as html table (rows 2:end in cell array of csv values)
cellfun(@(x)fprintf(1,['\n\t<tr>' sprintf('\n\t\t<td>%s</td>',x{:}) '\n\t</tr>']),tableValues(2:end))
fprintf(1,'\n</table>')
 

As a single line:

 
fprintf(1,['<table>\n\t<tr>\n\t\t<th>',regexprep(regexprep(regexprep(regexprep(regexprep(regexprep(regexprep(regexprep(fileread(cvsFileName),'&','&amp;'),'"','&quot;'),'<','&lt;'),'>','&gt;'),'(?<=(^[^\n\r]*)),','</th>\n\t\t<th>'),'(?<!>)(\r\n|\r|\n)','</td>\n\t<tr>\n\t</tr>\n\t\t<td>'),'</td>\n','</th>\n','once'),',','</td>\n\t\t<td>'),'</td>\n\t</tr>\n</table>\n'])
 
Output:
 
<table>
<tr>
<th>Character</th>
<th>Speech</th>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>
 

[edit] Maxima

infile: "input.csv";
outfile: "table.html";
instream: openr(infile);
outstream: openw(outfile);
 
printf(outstream, "<TABLE border=\"1\">~%");
nr: 0;
while (line: readline(instream))#false do (
nr: nr + 1,
line: ssubst("&lt;", "<", line),
line: ssubst("&gt;", ">", line),
value_list: map(lambda([f], strim(" ", f)), split(line, ",")),
if nr=1 then printf(outstream, " <THEAD bgcolor=\"yellow\">") else printf(outstream, " <TBODY bgcolor=\"orange\">"),
printf(outstream, "<TR>"),
for value in value_list do printf(outstream, "<TD>~a</TD>", value),
printf(outstream, "</TR>"),
if nr=1 then printf(outstream, "</THEAD>~%") else printf(outstream, "</TBODY>~%"));
printf(outstream, "</TABLE>~%");
 
close(instream);
close(outstream);
<TABLE border="1">
<THEAD bgcolor="yellow"><TR><TD>Character</TD><TD>Speech</TD></TR></THEAD>
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>Brians mother</TD><TD>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>Who are you?</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>Brians mother</TD><TD>I'm his mother; that's who!</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR></TBODY>
</TABLE>

[edit] ML/I

This example carries out the special formatting for extra credit. This is a macro rather than a function, though, due to the nature of ML/I.

[edit] Input

MCSKIP "WITH" NL
"" CSV to HTML
"" assumes macros on input stream 1, terminal on stream 2
MCSKIP MT,[]
MCSKIP SL WITH ~
MCINS %.
"" C1=th before header output, td afterwards
MCCVAR 1,2
MCSET C1=[th]
"" HTML escapes
MCDEF < AS [[&lt;]]
MCDEF > AS [[&gt;]]
MCDEF & AS [[&amp;]]
"" Main line processing
MCDEF SL N1 OPT , N1 OR NL ALL
AS [[ <tr>]
MCSET T2=1
%L1.MCGO L2 IF T2 GR T1
[<]%C1.[>]%AT2.[</]%C1.[>]
MCSET T2=T2+1
MCGO L1
%L2.[ </tr>]
MCSET C1=[td]
]
[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>HTML converted from CSV</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css"><!--
th {
font-weight:bold;
text-align:left
}
table,td,th {
border:1px solid;
border-collapse:collapse
}
td,th {
padding:10px
}
//-->
</style>
</head>
 
<body>
<table>]
MCSET S1=1
~MCSET S10=2
~MCSET S1=0
[</table>
</body>
</html>
]

[edit] Output

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>HTML converted from CSV</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css"><!--
th {
font-weight:bold;
text-align:left
}
table,td,th {
border:1px solid;
border-collapse:collapse
}
td,th {
padding:10px
}
//-->
</style>
</head>
 
<body>
<table>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a
very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>
</body>
</html>

[edit] NetRexx

Uses the NetRexx solution for Read a file line by line to read the CSV file into the program.

/* NetRexx */
options replace format comments java crossref symbols nobinary
 
parse arg inFileName .
if inFileName = '' | inFileName = '.' then inFileName = './data/Brian.csv'
csv = RREadFileLineByLine01.scanFile(inFileName)
 
header = htmlHeader()
pre = htmlCsvText(csv, inFileName)
table = htmlCsvTable(csv, inFileName)
footer = htmlFooter()
 
say header
say pre
say table
say footer
 
return
 
method htmlHeader() public static returns Rexx
html = '<?xml version="1.0" encoding="UTF-8"?>\n' -
|| '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n' -
|| '<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">\n' -
|| '<head>\n' -
|| '<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>\n' -
|| '<title>RCsv2Html</title>\n' -
|| '<style type="text/css">\n' -
|| '<!--\n' -
|| '/* <![DATA[ */\n' -
|| 'body {\n' -
|| ' font-family: "Verdana", "Geneva", "Helvetica Neue", "Helvetica", "DejaVu Sans", "Arial", sans-serif;\n' -
|| '}\n' -
|| 'table, th, td {\n' -
|| ' border: 1px solid black;\n' -
|| ' border-collapse: collapse;\n' -
|| ' padding: 0.25em;\n' -
|| ' font-size: 85%;\n' -
|| '}\n' -
|| 'th {\n' -
|| ' color: white;\n' -
|| ' background-color: green;\n' -
|| '}\n' -
|| 'p.classname {\n' -
|| ' font-size: inherit;\n' -
|| '}\n' -
|| '/* ]] */\n' -
|| '//-->\n' -
|| '</style>\n' -
|| '</head>\n' -
|| '<body>\n' -
|| '<h1>Rosetta Code &ndash; NetRexx Sample Output</h2>\n' -
|| '<h2><a href="http://rosettacode.org/wiki/CSV_to_HTML_translation">CSV to HTML translation</a></h2>\n' -
|| ''
 
return html
 
method htmlFooter() public static returns Rexx
html = '</body>\n' -
|| '</html>\n' -
|| ''
return html
 
method htmlCsvText(csv, fileName = '.') public static returns Rexx
html = '<h3>Contents of CSV <code>'fileName'</code></h3>\n' -
|| '<pre>\n' -
|| ''
loop row = 1 to csv[0]
html = html || csv[row]'\n'
end row
html = html -
|| '</pre>\n' -
|| ''
return html
 
method htmlCsvTable(csv, fileName = '.') public static returns Rexx
html = '<table>\n' -
|| '<caption>Translation of CSV <code>'fileName'</code></caption>\n' -
|| '<thead>\n' -
|| ''
html = html -
|| htmlCsvTableRow(csv[1], 'th')'\n' -
|| '</thead>\n' -
|| '<tbody>\n' -
|| ''
loop r_ = 2 to csv[0]
html = html -
|| htmlCsvTableRow(csv[r_])'\n' -
|| ''
end r_
html = html -
|| '</tbody>\n' -
|| '</table>\n' -
|| ''
return html
 
method htmlCsvTableRow(row, tag = 'td') public static returns Rexx
row = row.strip('t')
row = row.changestr('&', '&amp;') -- need to do this one first to avoid double translation
row = row.changestr('"', '&quot;')
row = row.changestr("'", '&apos;')
row = row.changestr('<', '&lt;')
row = row.changestr('>', '&gt;')
elmts = ''
elmts[0] = 0
e_ = 0
loop while row.length() > 0
parse row elmt ',' row
e_ = e_ + 1; elmts[0] = e_; elmts[e_] = elmt
end
html = '<tr>\n' -
|| ''
loop e_ = 1 to elmts[0]
html = html -
|| '<'tag'>'elmts[e_]'</'tag'>\n' -
|| ''
end e_
html = html -
|| '</tr>\n' -
|| ''
return html
 

Output:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
<title>RCsv2Html</title>
<style type="text/css">
<!--
/* <![DATA[ */
body {
font-family: "Verdana", "Geneva", "Helvetica Neue", "Helvetica", "DejaVu Sans", "Arial", sans-serif;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
padding: 0.25em;
font-size: 85%;
}
th {
color: white;
background-color: green;
}
p.classname {
font-size: inherit;
}
/* ]] */
//-->
</style>
</head>
<body>
<h1>Rosetta Code &ndash; NetRexx Sample Output</h2>
<h2><a href="http://rosettacode.org/wiki/CSV_to_HTML_translation">CSV to HTML translation</a></h2>
 
<h3>Contents of CSV <code>./data/Brian.csv</code></h3>
<pre>
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
</pre>
 
<table>
<caption>Contents of CSV <code>./data/Brian.csv</code></caption>
<thead>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
 
</thead>
<tbody>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
 
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He&apos;s not the messiah; he&apos;s a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
 
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
 
<tr>
<td>Brians mother</td>
<td>I&apos;m his mother; that&apos;s who!</td>
</tr>
 
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
 
</tbody>
</table>
 
</body>
</html>
 

Rendered Output:

RCsv2HtmlNetRexx.png

[edit] Nimrod

Translation of: Python
import cgi, strutils
 
const csvtext = """Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"""
 
proc row2tr(row): string =
result = "<tr>"
let cols = xmlEncode(row).split(",")
for col in cols:
result.add "<td>"&col&"</td>"
result.add "</tr>"
 
proc csv2html(txt): string =
result = "<table summary=\"csv2html program output\">\n"
for row in txt.splitLines():
result.add " <tbody>"&row2tr(row)&"</tbody>\n"
result.add "</table>"
 
echo csv2html(csvtext)
Output:
<table summary="csv2html program output">
  <tbody><tr><td>Character</td><td>Speech</td></tr></tbody>
  <tbody><tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr></tbody>
  <tbody><tr><td>Brians mother</td><td><angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry></td></tr></tbody>
  <tbody><tr><td>The multitude</td><td>Who are you?</td></tr></tbody>
  <tbody><tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr></tbody>
  <tbody><tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr></tbody>
</table>

[edit] OCaml

[edit] Simple solution

OCaml possesses a CSV module but we do not use it hereafter because the CSV data does not contain comas.

open Printf
 
let csv_data = "\
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; \
he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"

 
(* General HTML escape *)
let escape =
let html_escapes = Str.regexp "\\([^A-Za-z0-9 ;!?'/]\\)" in
let esc s = sprintf "&#%04d;" (Char.code s.[Str.group_beginning 1]) in
Str.global_substitute html_escapes esc
 
let nl = Str.regexp "\n\r?"
let coma = Str.regexp ","
 
let list_of_csv csv =
List.map (fun l -> Str.split coma l) (Str.split nl csv)
 
let print_html_table segments =
printf "<table>\n";
List.iter (fun line ->
printf "<tr>";
List.iter (fun c -> printf "<td>%s</td>" (escape c)) line;
printf "</tr>\n";
) segments;
printf "</table>\n";
;;
 
let () =
print_html_table (list_of_csv csv_data)
Sample html output:
<table> 
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&#0060;angry&#0062;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&#0060;/angry&#0062;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Extra credit solution

open Printf
 
let csv_data = "\
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; \
he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"

 
(* General HTML escape *)
let escape =
let html_escapes = Str.regexp "\\([^A-Za-z0-9 ;!?'/]\\)" in
let esc s = sprintf "&#%04d;" (Char.code s.[Str.group_beginning 1]) in
Str.global_substitute html_escapes esc
 
let nl = Str.regexp "\n\r?"
let coma = Str.regexp ","
 
let list_of_csv csv =
List.map (fun l -> Str.split coma l) (Str.split nl csv)
 
let print_html_table segments =
let print_row line =
printf "<tr>";
List.iter (fun c -> printf "<td>%s</td>" (escape c)) line;
printf "</tr>\n" in
printf "<html>
<head>
<style type=\"
text/css\">
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head>"
;
printf "<table>\n<thead>";
print_row (List.hd segments);
printf "</thead><tbody>\n";
List.iter print_row (List.tl segments);
printf "</tbody>\n</table>\n</html>";
;;
 
let () =
print_html_table (list_of_csv csv_data)
Output:
<html> 
<head>
<style type="text/css">
td {background-color:#ddddff; }
thead td {background-color:#ddffdd; text-align:center; }
</style>
</head><table>
<thead><tr><td>Character</td><td>Speech</td></tr>
</thead><tbody>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&#0060;angry&#0062;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&#0060;/angry&#0062;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</tbody>
</table>
</html>

[edit] OpenEdge/Progress

 
FUNCTION csvToHtml RETURNS CHARACTER (
i_lhas_header AS LOGICAL,
i_cinput AS CHARACTER
):
 
DEFINE VARIABLE coutput AS CHARACTER NO-UNDO.
 
DEFINE VARIABLE irow AS INTEGER NO-UNDO.
DEFINE VARIABLE icolumn AS INTEGER NO-UNDO.
DEFINE VARIABLE crow AS CHARACTER NO-UNDO.
DEFINE VARIABLE ccell AS CHARACTER NO-UNDO.
 
coutput = "<html>~n~t<table>".
 
DO irow = 1 TO NUM-ENTRIES( i_cinput, "~n":U ):
 
coutput = coutput + "~n~t~t<tr>".
 
crow = ENTRY( irow, i_cinput, "~n":U ).
 
DO icolumn = 1 TO NUM-ENTRIES( crow ):
ccell = ENTRY( icolumn, crow ).
 
coutput = coutput + "~n~t~t~t" + IF i_lhas_header AND irow = 1 THEN "<th>" ELSE "<td>".
coutput = coutput + REPLACE( REPLACE( REPLACE( ccell, "&", "&amp;" ), "<", "&lt;" ), ">", "&gt;" ).
coutput = coutput + IF i_lhas_header AND irow = 1 THEN "</th>" ELSE "</td>".
 
END.
 
coutput = coutput + "~n~t~t</tr>".
 
END.
 
coutput = coutput + "~n~t</table>~n</html>".
 
RETURN coutput.
 
END FUNCTION. /* csvToHtml */
 
MESSAGE
csvToHtml(
TRUE,
"Character,Speech" + "~n" +
"The multitude,The messiah! Show us the messiah!" + "~n" +
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>" + "~n" +
"The multitude,Who are you?" + "~n" +
"Brians mother,I'm his mother; that's who!" + "~n" +
"The multitude,Behold his mother! Behold his mother!"
)
VIEW-AS ALERT-BOX.
with header enabled:
<html>
<table>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>
</html>

[edit] Perl

Provide the CSV data as standard input. With a command-line argument, the first row will use <th> instead of <td>.

use HTML::Entities;
 
sub row {
my $elem = shift;
my @cells = map {"<$elem>$_</$elem>"} split ',', shift;
print '<tr>', @cells, "</tr>\n";
}
 
my ($first, @rest) = map
{my $x = $_; chomp $x; encode_entities $x}
<STDIN>;
print "<table>\n";
row @ARGV ? 'th' : 'td', $first;
row 'td', $_ foreach @rest;
print "</table>\n";
Output (with a command-line argument):
<table>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&#39;s not the messiah; he&#39;s a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I&#39;m his mother; that&#39;s who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Perl 6

A very lispy solution:

my $str = "Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"
;
 
# comment the next line out, if you want to read from standard input instead of the hard-coded $str above
# my $str = $*IN.slurp;
 
my &escape = *.trans([ <& < \>>] => [<&amp; &lt; &gt;> ]); # a function with one argument that escapes the entities
my &tag = {"<$^tag>"~$^what~"</$^tag>"};
 
printf
'<!DOCTYPE html>
<html>
<head><title>Some Text</title></head>
<body><table>
%s
</table></body></html>
'
, [~] # concatenation reduction ('a', 'b', 'c') → 'abc'
(escape($str).split(/\n/) # escape the string and split at newline
==> map -> $line {tag 'tr', # feed that into a map, that map function will tag as 'tr, and has an argument called $line
([~] $line.split(/','/)\ # split $line at ',',
# that / at the end is just an unspace, you can omit it, but then you have to delete
# all whitespace and comments between split(…) and .map
.map({tag 'td', $^cell}))})\ # map those cells as td
.join("\n"); # append a newline for nicer output
Output:
<!DOCTYPE html>
<html>
<head><title>Some Text</title></head>
<body><table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table></body></html>

[edit] PHP

[edit] Simple Solution

 
<?php
$csv = <<<EOT
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
EOT
;
 
function convert($csv)
{
$out = [];
array_map(function($ln) use(&$out) {
$ln = htmlentities($ln);
$out[] = count($out) == 0
 ? '<thead><tr><th>'.implode('</th><th>',explode(',',$ln))."</th></tr></thead>\n"
: '<tr><td>'.implode('</td><td>',explode(',',$ln))."</td></tr>\n";
}, explode("\n",$csv));
return '<table>'.implode('',$out).'</table>';
}
 
echo convert($csv);
 

[edit] PicoLisp

[edit] Simple solution

(load "@lib/http.l")
 
(in "text.csv"
(<table> 'myStyle NIL NIL
(prinl)
(while (split (line) ",")
(<row> NIL (ht:Prin (pack (car @))) (ht:Prin (pack (cadr @))))
(prinl) ) ) )
Output:
<table class="myStyle">
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Extra credit solution

(load "@lib/http.l")
 
(in "text.csv"
(when (split (line) ",")
(<table> 'myStyle NIL (mapcar '((S) (list NIL (pack S))) @)
(prinl)
(while (split (line) ",")
(<row> NIL (ht:Prin (pack (car @))) (ht:Prin (pack (cadr @))))
(prinl) ) ) ) )
Output:
<table class="myStyle"><tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] PowerShell

[edit] Simple solution

 
Import-Csv -Path .\csv_html_test.csv | ConvertTo-Html -Fragment | Out-File .\csv_html_test.html
 
Output:
<table>
<colgroup>
<col/>
<col/>
</colgroup>
<tr><th>Character</th><th>Speech </th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah! </td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt; </td></tr>
 
<tr><td>The multitude</td><td>Who are you? </td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who! </td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother! </td></tr>
</table>

[edit] Extra credit solution

 
$htmlformat = '<title>Csv to Html</title>'
$htmlformat += '<style type="text/css">'
$htmlformat += 'BODY{background-color:#663300;color:#FFCC00;font-family:Arial Narrow,sans-serif;font-size:17px;}'
$htmlformat += 'TABLE{border-width: 3px;border-style: solid;border-color: black;border-collapse: collapse;}'
$htmlformat += 'TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:#663333}'
$htmlformat += 'TD{border-width: 1px;padding: 8px;border-style: solid;border-color: black;background-color:#660033}'
$htmlformat += '</style>'
Import-Csv -Path .\csv_html_test.csv | ConvertTo-Html -Head $htmlformat -Body '<h1>Csv to Html</h1>' | Out-File .\csv_html_test.html
Invoke-Expression .\csv_html_test.html
 
Output:
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Csv to Html</title><style type="text/css">BODY{background-color:#663300;color:#FFCC00;font-family:Arial Narrow,sans-serif;font-size:17px;}TABLE{border-width: 3px;border-style: solid;border-color: black;border-collapse: collapse;}TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:#663333}TD{border-width: 1px;padding: 8px;border-style: solid;border-color: black;background-color:#660033}</style>
</head><body>
<h1>Csv to Html</h1>
<table>
<colgroup>
<col/>
<col/>
</colgroup>
<tr><th>Character</th><th>Speech </th></tr>
 
<tr><td>The multitude</td><td>The messiah! Show us the messiah! </td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt; </td></tr>
<tr><td>The multitude</td><td>Who are you? </td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who! </td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother! </td></tr>
 
</table>
</body></html>
 

[edit] Prolog

Uses DCG.

Works with: SWI-Prolog

[edit] Simple solution

csv_html :-
L = "Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!",
 
csv_html(L, Out, []),
string_to_list(Str, Out),
writeln(Str).
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% simple HTML
%
csv_html(L) -->
"<TABLE>\n",
csv_tr(L),
"</TABLE>".
 
csv_tr([]) --> [].
 
csv_tr(L) -->
"<TR>\n",
csv_td(L, S),
"\n</TR>\n",
csv_tr(S).
 
csv_td(L, S) -->
"<TD>",
csv_td_in(L, S),
"</TD>".
 
csv_td_in([], []) --> [].
 
csv_td_in([10|L], L) --> [].
 
csv_td_in([44|L], S) -->
"</TD><TD>",
csv_td_in(L,S).
 
csv_td_in([60|T], S) -->
"&lt;",
csv_td_in(T, S).
 
csv_td_in([62|T], S) -->
"&gt;",
csv_td_in(T, S).
 
csv_td_in([H|T], S) -->
[H],
csv_td_in(T, S).
 
 
Output:
<TABLE>
<TR>
<TD>Character</TD><TD>Speech</TD>
</TR>
<TR>
<TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD>
</TR>
<TR>
<TD>Brians mother</TD><TD>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!>&lt;/angry&gt;</TD>
</TR>
<TR>
<TD>The multitude</TD><TD>Who are you?</TD>
</TR>
<TR>
<TD>Brians mother</TD><TD>I'm his mother; that's who!</TD>
</TR>
<TR>
<TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD>
</TR>
</TABLE>
 

[edit] Extra credit solution

csv_html_plus :-
L =
"Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!",
 
csv_html_plus(L, Out1, []),
string_to_list(Str1, Out1),
writeln(Str1).
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% HTML +
%
csv_html_plus(L) -->
"<TABLE>\n",
csv_head(L, R),
csv_body(R),
"</TABLE>".
 
 
csv_head(L, R) -->
"<THEAD>\n",
csv_head_tr(L, R),
"</THEAD>\n".
 
 
csv_head_tr(L, R) -->
"<TR>\n",
csv_head_th(L, R),
"\n</TR>\n".
 
 
csv_head_th(L, S) -->
"<TH style='color:#000; background:#FF0;'>",
csv_head_th_in(L, S),
"</TH>".
 
csv_head_th_in([], []) --> [].
 
csv_head_th_in([10|L], L) --> [].
 
csv_head_th_in([44|L], S) -->
"</TH><TH style='color:#000; background:#FF0;'>",
csv_head_th_in(L,S).
 
csv_head_th_in([H|T], S) -->
[H],
csv_head_th_in(T, S).
 
 
csv_body(L) -->
"<TBODY>\n",
csv_body_tr(L),
"</TBODY>\n".
 
csv_body_tr([]) --> [].
 
csv_body_tr(L) -->
"<TR>\n",
csv_body_td(L, S),
"\n</TR>\n",
csv_body_tr(S).
 
csv_body_td(L, S) -->
"<TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>",
csv_body_td_in(L, S),
"</TD>".
 
csv_body_td_in([], []) --> [].
 
csv_body_td_in([10|L], L) --> [].
 
csv_body_td_in([44|L], S) -->
"</TD><TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>",
csv_body_td_in(L,S).
 
csv_body_td_in([60|T], S) -->
"&lt;",
csv_body_td_in(T, S).
 
csv_body_td_in([62|T], S) -->
"&gt;",
csv_body_td_in(T, S).
 
csv_body_td_in([H|T], S) -->
[H],
csv_body_td_in(T, S).
 
Output:
<TABLE>
<THEAD>
<TR>
<TH style='color:#000; background:#FF0;'>Character</TH><TH style='color:#000; background:#FF0;'>Speech</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>The multitude</TD><TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>The messiah! Show us the messiah!</TD>
</TR>
<TR>
<TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>Brians mother</TD><TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!>&lt;/angry&gt;</TD>
</TR>
<TR>
<TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>The multitude</TD><TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>Who are you?</TD>
</TR>
<TR>
<TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>Brians mother</TD><TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>I'm his mother; that's who!</TD>
</TR>
<TR>
<TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>The multitude</TD><TD style='color:#000; background:#8FF; border:1px #000 solid; padding:0.6em;'>Behold his mother! Behold his mother!</TD>
</TR>
</TBODY>
</TABLE>
 

[edit] HTML outputs rendered in firefox browser

Prolog csv to html-1.png

[edit] Python

(Note: rendered versions of both outputs are shown at the foot of this section).

[edit] Simple solution

csvtxt = '''\
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!\
'''

 
from cgi import escape
 
def _row2tr(row, attr=None):
cols = escape(row).split(',')
return ('<TR>'
+ ''.join('<TD>%s</TD>' % data for data in cols)
+ '</TR>')
 
def csv2html(txt):
htmltxt = '<TABLE summary="csv2html program output">\n'
for rownum, row in enumerate(txt.split('\n')):
htmlrow = _row2tr(row)
htmlrow = ' <TBODY>%s</TBODY>\n' % htmlrow
htmltxt += htmlrow
htmltxt += '</TABLE>\n'
return htmltxt
 
htmltxt = csv2html(csvtxt)
print(htmltxt)

Sample HTML output

<TABLE summary="csv2html program output">
<TBODY><TR><TD>Character</TD><TD>Speech</TD></TR></TBODY>
<TBODY><TR><TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR></TBODY>
<TBODY><TR><TD>Brians mother</TD><TD>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</TD></TR></TBODY>
<TBODY><TR><TD>The multitude</TD><TD>Who are you?</TD></TR></TBODY>
<TBODY><TR><TD>Brians mother</TD><TD>I'm his mother; that's who!</TD></TR></TBODY>
<TBODY><TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR></TBODY>
</TABLE>

[edit] Extra credit solution

def _row2trextra(row, attr=None):
cols = escape(row).split(',')
attr_tr = attr.get('TR', '')
attr_td = attr.get('TD', '')
return (('<TR%s>' % attr_tr)
+ ''.join('<TD%s>%s</TD>' % (attr_td, data) for data in cols)
+ '</TR>')
 
def csv2htmlextra(txt, header=True, attr=None):
' attr is a dictionary mapping tags to attributes to add to that tag'
 
attr_table = attr.get('TABLE', '')
attr_thead = attr.get('THEAD', '')
attr_tbody = attr.get('TBODY', '')
htmltxt = '<TABLE%s>\n' % attr_table
for rownum, row in enumerate(txt.split('\n')):
htmlrow = _row2trextra(row, attr)
rowclass = ('THEAD%s' % attr_thead) if (header and rownum == 0) else ('TBODY%s' % attr_tbody)
htmlrow = ' <%s>%s</%s>\n' % (rowclass, htmlrow, rowclass[:5])
htmltxt += htmlrow
htmltxt += '</TABLE>\n'
return htmltxt
 
htmltxt = csv2htmlextra(csvtxt, True,
dict(TABLE=' border="1" summary="csv2html extra program output"',
THEAD=' bgcolor="yellow"',
TBODY=' bgcolor="orange"'
)
)
print(htmltxt)

Sample HTML output

<TABLE border="1" summary="csv2html extra program output">
<THEAD bgcolor="yellow"><TR><TD>Character</TD><TD>Speech</TD></TR></THEAD>
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>Brians mother</TD><TD>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>Who are you?</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>Brians mother</TD><TD>I'm his mother; that's who!</TD></TR></TBODY>
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR></TBODY>
</TABLE>

[edit] HTML outputs rendered in firefox browser

Csv2html.PNG

[edit] Racket

Uses X-exprs:

#lang racket
 
(define e.g.-CSV
(string-join
'("Character,Speech"
"The multitude,The messiah! Show us the messiah!"
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>"
"The multitude,Who are you?"
"Brians mother,I'm his mother; that's who!"
"The multitude,Behold his mother! Behold his mother!")
"\n"))
 
(define (CSV-lines->HTML-table csv)
(define csv-rows
(regexp-split "\n" csv))
(define csv-row-cells
(map (lambda (row) (regexp-split "," row)) csv-rows))
(define (cell-data->HTML-data data)
`(td () ,data))
(define (row-data->HTML-row CSV-row)
`(tr () ,@(map cell-data->HTML-data CSV-row) "\n"))
`(table
(thead
,(row-data->HTML-row (car csv-row-cells)))
(tbody ,@(map row-data->HTML-row (cdr csv-row-cells)))))
 
(require xml)
(display (xexpr->string (CSV-lines->HTML-table e.g.-CSV)))

Sample HTML output:

<table><thead><tr><td>Character</td><td>Speech</td>
</tr></thead><tbody><tr><td>The multitude</td><td>The messiah! Show us the messiah!</td>
</tr><tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr><tr><td>The multitude</td><td>Who are you?</td>
</tr><tr><td>Brians mother</td><td>I'm his mother; that's who!</td>
</tr><tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td>
</tr></tbody></table>

[edit] Retro

remapping off
"Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!" remapping on
keepString constant CSV
 
: display ( c- )
[ ', = ] [ drop "</td><td>" puts ] when
[ 10 = ] [ drop "</td></tr>\n<tr><td>" puts ] when
[ '< = ] [ drop "&lt;" puts ] when
[ '> = ] [ drop "&gt;" puts ] when
[ '& = ] [ drop "&amp;" puts ] when
putc ;
 
: displayHTML ( $- )
"<table>\n<tr><td>" puts
[ @ display ] ^types'STRING each@
"</td></tr>\n</table>" puts ;
 
CSV displayHTML
Output:
<table>
<tr><td>Character</td><td>Speech</td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] REXX

The rendered output was verified using Firefox Aurora with:

  •   file:///c:/output.html
  •   file:///c:/outputh.html
/*REXX program to convert CSV ───► HTML table representing the CSV data.*/
arg header_ . /*see if the user wants a header.*/
wantsHdr= (header_=='HEADER') /*arg (low/upp/mix case)=HEADER ?*/
 
iFID= 'CSV_HTML.TXT' /*the input fileID. */
if wantsHdr then oFID= 'OUTPUTH.HTML' /*output fileID with header, */
else oFID= 'OUTPUT.HTML' /* " " without header. */
 
do rows=0 while lines(iFID)\==0 /*read the rows from a (txt) file*/
row.rows=strip(linein(iFID))
end /*rows*/
 
convFrom= '& < > "' /*special characters to convert. */
convTo = '&amp; &lt; &gt; &quot;' /*what they are converted into. */
 
call write , '<html>'
call write , '<table border=4 cellpadding=9 cellspacing=1>'
 
do j=0 for rows; call write 5, '<tr>'
tx='td'
if wantsHdr & j==0 then tx='th'
 
do while row.j\==''; parse var row.j yyy ',' row.j
do k=1 for words(convFrom)
yyy=changestr(word(convFrom,k),yyy,word(convTo,k))
end /*k*/
call write 10, '<'tx">"yyy'</'tx">"
end /*forever*/
end /*j*/
 
call write 5, '<tr>'
call write , '</table>'
call write , '</html>'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────WRITE subroutine────────────────────*/
write: call lineout oFID, left('', 0 || arg(1))arg(2); return

Some older REXXes don't have a   changestr   BIF, so one is included here ──►   CHANGESTR.REX.

Output:
<html>
<table border=4 cellpadding=9 cellspacing=1>
     <tr>
          <td>Character</td>
          <td>Speech</td>
     <tr>
          <td>The multitude</td>
          <td>The messiah! Show us the messiah!</td>
     <tr>
          <td>Brians mother</td>
          <td><angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry></td>
     <tr>
          <td>The multitude</td>
          <td>Who are you?</td>
     <tr>
          <td>Brians mother</td>
          <td>I'm his mother; that's who!</td>
     <tr>
          <td>The multitude</td>
          <td>Behold his mother! Behold his mother!</td>
     <tr>
</table>
</html>
rendered output:
Character Speech
The multitude The messiah! Show us the messiah!
Brians mother <angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude Who are you?
Brians mother I'm his mother; that's who!
The multitude Behold his mother! Behold his mother!
(extra credit solution):
when the first argument is HEADER

in upper/lower/mixed case, with/without leading/trailing blanks.

<html>
<table border=4 cellpadding=9 cellspacing=1>
     <tr>
          <th>Character</th>
          <th>Speech</th>
     <tr>
          <td>The multitude</td>
          <td>The messiah! Show us the messiah!</td>
     <tr>
          <td>Brians mother</td>
          <td><angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry></td>
     <tr>
          <td>The multitude</td>
          <td>Who are you?</td>
     <tr>
          <td>Brians mother</td>
          <td>I'm his mother; that's who!</td>
     <tr>
          <td>The multitude</td>
          <td>Behold his mother! Behold his mother!</td>
     <tr>
</table>
</html>
rendered output:
Character Speech
The multitude The messiah! Show us the messiah!
Brians mother <angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude Who are you?
Brians mother I'm his mother; that's who!
The multitude Behold his mother! Behold his mother!

[edit] Ruby

The extra credit version has one extra line compared to the non-extra credit version. To output a header, simply add "header" to the command line:

 ruby csv2html.rb header

I/O is done through standard input/output.

require 'cgi'
 
puts '<table summary="csv2html program output">'
 
def row2html str, wrap = "td"
"<tr>" +
str.split(",").map { |cell| "<#{wrap}>#{CGI.escapeHTML cell}</#{wrap}>" }.join +
"</tr>"
end
 
puts row2html gets.chomp, "th" if ARGV.delete "header"
 
while str = gets
puts row2html str.chomp
end
 
puts "</table>"
Output:
<table summary="csv2html program output">
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] Run BASIC

The extra credit version has 2 extra lines of code to get the heading.

csv$ = "Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"
 
k = instr(csv$,",") ' 2 exra lines to get heading
csv$ = left$(csv$,k - 1) + "</th><th> + mid$(csv$,k + 1)
 
csv$ = strRep$(csv$,",","</td><td>")
html "<table border=1><TR bgcolor=wheat align=center><th>";strRep$(csv$,chr$(13),"</td></tr><tr><td>");"</td></tr></table"
wait
' --------------------------------
' string replace rep str with
' --------------------------------
FUNCTION strRep$(strRep$,rep$,with$)
ln = len(rep$)
k = instr(strRep$,rep$)
while k
strRep$ = left$(strRep$,k - 1) + with$ + mid$(strRep$,k + ln)
k = instr(strRep$,rep$)
WEND
END FUNCTION
Output:
CharacterSpeech
The multitudeThe messiah! Show us the messiah!
Brians mother<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitudeWho are you?
Brians motherI'm his mother; that's who!
The multitudeBehold his mother! Behold his mother!

[edit] Scala

Scala has built-in support for XML, so you can freely mix XML literals into your Scala source code. This is nice, because instead of using strings to represent XML, you create XML literals that the compiler can understand and verify. This approach lets you easily generate dynamic XML by interweaving Scala code and XML in the same expressions.
object CsvToHTML extends App {
val header = <head>
<title>CsvToHTML</title>
<style type="text/css">
td {{background-color:#ddddff; }} thead td {{background-color:#ddffdd; text-align:center; }}
</style>
</head>
val csv =
"""Character,Speech
|The multitude,The messiah! Show us the messiah!
|Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
|The multitude,Who are you?
|Brians mother,I'm his mother; that's who!
|The multitude,Behold his mother! Behold his mother!"
"".stripMargin
 
def csv2html(csv: String, withHead: Boolean) = {
 
def processRow(text: String) = <tr>
{text.split(',').map(s => <td>
{s}
</td>)}
</tr>
 
val (first :: rest) = csv.lines.toList // Separate the header and the rest
 
def tableHead = if (withHead)
<thead>
{processRow(first)}
</thead>
else processRow(first)
 
<html>
{header}<body>
<table>
{tableHead}{rest.map(processRow)}
</table>
</body>
</html>
}
 
println(csv2html(csv, true))
}
Output:
<html>
<head>
<title>CsvToHTML</title>
<style type="text/css">
td {background-color:#ddddff; } thead td {background-color:#ddffdd; text-align:center; }
</style>
</head><body>
<table>
<thead>
<tr>
<td>
Character
</td><td>
Speech
</td>
</tr>
</thead><tr>
<td>
The multitude
</td><td>
The messiah! Show us the messiah!
</td>
</tr><tr>
<td>
Brians mother
</td><td>
&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;
</td>
</tr><tr>
<td>
The multitude
</td><td>
Who are you?
</td>
</tr><tr>
<td>
Brians mother
</td><td>
I'm his mother; that's who!
</td>
</tr><tr>
<td>
The multitude
</td><td>
Behold his mother! Behold his mother!
</td>
</tr>
</table>
</body>
</html>

[edit] Sed

File csv2html.sed

#!/bin/sed -f
 
s|<|\&lt;|g
s|>|\&gt;|g
s|^| <tr>\n <td>|
s|,|</td>\n <td>|
s|$|</td>\n </tr>|
1s|^|<table>\n|
$s|$|\n</table>|
$ sed -f csv2html.sed input.csv
<table>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] Seed7

The library html_ent.s7i defines the function encodeHtmlContent, which replaces characters with HTML entities. E.g.: '<' is replaced by &lt;.

$ include "seed7_05.s7i";
include "html_ent.s7i";
 
const string: csvData is "\
\Character,Speech\n\
\The multitude,The messiah! Show us the messiah!\n\
\Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>\n\
\The multitude,Who are you?\n\
\Brians mother,I'm his mother; that's who!\n\
\The multitude,Behold his mother! Behold his mother!\n";
 
const proc: main is func
local
var string: line is "";
var string: column is "";
const array [boolean] string: columnStartTag is [boolean] ("<td>", "<th>");
const array [boolean] string: columnEndTag is [boolean] ("</td>", "</th>");
var boolean: firstLine is TRUE;
begin
writeln("<table>");
for line range split(csvData, '\n') do
write("<tr>");
for column range split(line, ',') do
write(columnStartTag[firstLine] <& encodeHtmlContent(column) <& columnEndTag[firstLine]);
end for;
writeln("</tr>");
firstLine := FALSE;
end for;
writeln("</table>");
end func;
Output:
 
<table>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry></td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
<tr><td></td></tr>
</table>
 
Output:
viewed with a browser:
CharacterSpeech
The multitudeThe messiah! Show us the messiah!
Brians mother<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitudeWho are you?
Brians motherI'm his mother; that's who!
The multitudeBehold his mother! Behold his mother!

[edit] Tcl

Library: Tcllib (Package: csv)
Library: Tcllib (Package: html)
Library: Tcllib (Package: struct::queue)
package require Tcl 8.5
package require csv
package require html
package require struct::queue
 
set csvData "Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"

 
struct::queue rows
foreach line [split $csvData "\n"] {
csv::split2queue rows $line
}
html::init
puts [subst {
[html::openTag table {summary="csv2html program output"}]
[html::while {[rows size]} {
[html::row {*}[html::quoteFormValue [rows get]]]
}]
[html::closeTag]
}]

Extra credit version:

package require Tcl 8.5
package require csv
package require html
package require struct::queue
 
set csvData "Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!"

 
html::init {
table.border 1
table.summary "csv2html program output"
tr.bgcolor orange
}
 
# Helpers; the html package is a little primitive otherwise
proc table {contents {opts ""}} {
set out [html::openTag table $opts]
append out [uplevel 1 [list subst $contents]]
append out [html::closeTag]
}
proc tr {list {ropt ""}} {
set out [html::openTag tr $ropt]
foreach x $list {append out [html::cell "" $x td]}
append out [html::closeTag]
}
 
# Parse the CSV data
struct::queue rows
foreach line [split $csvData "\n"] {
csv::split2queue rows $line
}
 
# Generate the output
puts [subst {
[table {
[tr [html::quoteFormValue [rows get]] {bgcolor="yellow"}]
[html::while {[rows size]} {
[tr [html::quoteFormValue [rows get]]]
}]
}]
}]
Output:
<table border="1" summary="csv2html program output">
<tr bgcolor="yellow"><td>Character</td><td>Speech</td></tr>
<tr bgcolor="orange"><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr bgcolor="orange"><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He&#39;s not the messiah; he&#39;s a very naughty boy! Now go away! &lt;/angry&gt;</td></tr>
<tr bgcolor="orange"><td>The multitude</td><td>Who are you?</td></tr>
<tr bgcolor="orange"><td>Brians mother</td><td>I&#39;m his mother; that&#39;s who!</td></tr>
<tr bgcolor="orange"><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] TUSCRIPT

 
$$ MODE TUSCRIPT
MODE DATA
$$ csv=*
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
$$ htmlhead=*
<!DOCTYPE html system>
<html>
<head>
<title>Life of Brian</title>
<style type="text/css">
th {background-color:orange}
td {background-color:yellow}
</style></head><body><table>
$$ BUILD X_TABLE txt2html=*
<< &lt;
>> &gt;
$$ MODE TUSCRIPT
file="brian.html"
ERROR/STOP CREATE (file,FDF-o,-std-)
csv=EXCHANGE (csv,txt2html)
x=SPLIT (csv,":,:",row1,row2)
ACCESS html: WRITE/ERASE/RECORDS/UTF8 $file s,html
WRITE html htmlhead
LOOP n,td1=row1,td2=row2
IF (n==1) THEN
row=CONCAT ("<tr><th>",td1,"</th><th>",td2,"</th></tr>")
ELSE
row=CONCAT ("<tr><td>",td1,"</td><td>",td2,"</td></tr>")
ENDIF
WRITE html row
ENDLOOP
WRITE html "</table></body></html>"
ENDACCESS/PRINT html
 

[edit] Output (source code)

<!DOCTYPE html system>
<html>
<head>
<title>Life of Brian</title>
<style type="text/css">
th {background-color:orange}
td {background-color:yellow}
</style></head><body><table>
<tr><th>Character</th><th>Speech</th></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table></body></html>
 

[edit] Output (rendered)

rendered by browser


[edit] TXR

[edit] Simple

@(collect)
@char,@speech
@(end)
@(output :filter :to_html)
<table>
@ (repeat)
<tr>
<td>@char</td>
<td>@speech</td>
</tr>
@ (end)
</table>
@(end)
Output:
$ txr csv.txr  csv.txt
<table>
<tr>
<td>Character</td>
<td>Speech</td>
</tr>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] With Styling

@(collect)
@char,@speech
@(end)
@(output :filter :to_html)
<style type="text/css">
tr.odd td {
background-color: #CC9999; color: black;
}
tr.even td {
background-color: #9999CC; color: black;
}
th {
background-color: #99CC99; color: black;
}
</style>
<table>
@ (repeat :counter row)
<tr class="@(if (evenp row) 'even 'odd)">
<td>@char</td>
<td>@speech</td>
</tr>
@ (first)
<tr>
<th>@char</th>
<th>@speech</th>
</tr>
@ (end)
</table>
@(end)
Output:
$ txr csv2.txr  csv.txt
<style type="text/css">
tr.odd td {
background-color: #CC9999; color: black;
}
tr.even td {
background-color: #9999CC; color: black;
}
th {
background-color: #99CC99; color: black;
}
</style>
<table>
<tr>
<th>Character</th>
<th>Speech</th>
</tr>
<tr class="odd">
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr class="even">
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td>
</tr>
<tr class="odd">
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr class="even">
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr class="odd">
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>

[edit] UNIX Shell

Works with: bash
Works with: ksh
csv2html() {
IFS=,
echo "<table>"
 
echo "<thead>"
read -r speaker text
htmlrow "$speaker" "$text" th
echo "</thead>"
 
echo "<tbody>"
while read -r speaker text; do
htmlrow "$speaker" "$text"
done
echo "</tbody>"
echo "</table>"
}
 
htmlrow() {
cell=${3:-td}
printf "<tr><%s>%s</%s><%s>%s</%s></tr>\n" \
"$cell" "$(escape_html "$1")" "$cell" \
"$cell" "$(escape_html "$2")" "$cell"
}
 
escape_html() {
str=${1//\&/&amp;}
str=${str//</&lt;}
str=${str//>/&gt;}
echo "$str"
}
 
html=$(
csv2html <<-END
Character,Speech
The multitude,The messiah! Show us the messiah!
Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude,Who are you?
Brians mother,I'm his mother; that's who!
The multitude,Behold his mother! Behold his mother!
END
)
echo "$html"
Output:
<table>
<thead>
<tr><th>Character</th><th>Speech</th></tr>
</thead>
<tbody>
<tr><td>The multitude</td><td>The messiah! Show us the messiah!</td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt;</td></tr>
<tr><td>The multitude</td><td>Who are you?</td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who!</td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</tbody>
</table>

[edit] Vedit macro language

This solution converts the table in-place in current edit buffer. If a block is highlighted, only the block is converted. If no block highlighted, the entire file is converted.

if (BB < 0) {           // block not set
BB(0) // convert entire file
BE(File_Size)
}
 
// Convert special characters into entities
Replace_Block("&","&amp;", BB, BE, BEGIN+ALL+NOERR)
Replace_Block("<","&lt;", BB, BE, BEGIN+ALL+NOERR)
Replace_Block(">","&gt;", BB, BE, BEGIN+ALL+NOERR)
 
// Convert CSV into HTML table
Goto_Pos(BB)
IT('<table>') IN
#80 = Cur_Pos
Goto_Pos(BE)
IT("</table>")
#81 = Cur_Line
IN
Goto_Pos(#80)
while (Cur_Line < #81) {
IT(" <tr><td>")
Replace_Block(",","</td><td>",Cur_Pos,EOL_Pos,ALL+NOERR)
EOL
IT("</td></tr>")
Line(1)
}
BB(Clear)
Output:
<table>
<tr><td>Character</td><td>Speech </td></tr>
<tr><td>The multitude</td><td>The messiah! Show us the messiah! </td></tr>
<tr><td>Brians mother</td><td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!&lt;/angry&gt; </td></tr>
<tr><td>The multitude</td><td>Who are you? </td></tr>
<tr><td>Brians mother</td><td>I'm his mother; that's who! </td></tr>
<tr><td>The multitude</td><td>Behold his mother! Behold his mother!</td></tr>
</table>

[edit] XSLT 2.0

[edit] Setup

  1. Download to a local copy of the csv-to-xml.xslt library style-sheet listed in the linked blog entry. Alternatively a copy of the style-sheet on this wiki can be found here: csv-to-xml.xslt
  2. Pass as the URI of the input csv as a parameter (named url-of-csv) to your XSLT 2.0 processor
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xcsvt="http://www.seanbdurkin.id.au/xslt/csv-to-xml.xslt"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xcsv="http://www.seanbdurkin.id.au/xslt/xcsv.xsd"
version="2.0"
exclude-result-prefixes="xsl xs xcsvt xcsv">
<xsl:import href="csv-to-xml.xslt" />
<xsl:output indent="yes" encoding="UTF-8" method="html" doctype-system="about:legacy-compat" />
<xsl:import-schema schema-location="http://www.seanbdurkin.id.au/xslt/xcsv.xsd"
use-when="system-property('xsl:is-schema-aware')='yes'" />
<xsl:param name="url-of-csv" as="xs:string" select="'roseta.csv'" />
 
 
<xsl:variable name="phase-1-result">
<xsl:call-template name="xcsvt:main" />
</xsl:variable>
 
<xsl:template match="/">
<html lang="en">
<head><title>CSV to HTML translation - Extra Credit</title></head>
<body>
<xsl:apply-templates select="$phase-1-result" mode="phase-2" />
</body>
</html>
</xsl:template>
 
<xsl:template match="xcsv:comma-separated-single-line-values" mode="phase-2">
<table>
<xsl:apply-templates mode="phase-2" />
</table>
</xsl:template>
 
<xsl:template match="xcsv:row[1]" mode="phase-2">
<th>
<xsl:apply-templates mode="phase-2" />
</th>
</xsl:template>
 
<xsl:template match="xcsv:row" mode="phase-2">
<tr>
<xsl:apply-templates mode="phase-2" />
</tr>
</xsl:template>
 
<xsl:template match="xcsv:value" mode="phase-2">
<td>
<xsl:apply-templates mode="phase-2" />
</td>
</xsl:template>
 
<xsl:template match="xcsv:notice" mode="phase-2" />
 
</xsl:stylesheet>

This style-sheet, when applied to the task input, yields...

<!DOCTYPE html
SYSTEM "about:legacy-compat">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>CSV to HTML translation - Extra Credit</title>
</head>
<body>
<table>
<th>
<td>Character</td>
<td>Speech</td>
</th>
<tr>
<td>The multitude</td>
<td>The messiah! Show us the messiah!</td>
</tr>
<tr>
<td>Brians mother</td>
<td>&lt;angry&gt;Now you listen here! He's not the messiah; he's a very naughty boy! Now go
away!&lt;/angry&gt;
</td>
</tr>
<tr>
<td>The multitude</td>
<td>Who are you?</td>
</tr>
<tr>
<td>Brians mother</td>
<td>I'm his mother; that's who!</td>
</tr>
<tr>
<td>The multitude</td>
<td>Behold his mother! Behold his mother!</td>
</tr>
</table>
</body>
</html>

[edit] zkl

csvData:=Data(0,Int,"Character,Speech\n"
"The multitude,The messiah! Show us the messiah!\n"
"Brians mother,<angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>\n"
"The multitude,Who are you\n"
"Brians mother,I'm his mother; that's who!\n"
"The multitude,Behold his mother! Behold his mother!");
 
html:=csvData.pump("<table>\n",fcn(line){
line.replace("&","&amp;").replace("<","&lt;") // <angry/> --> &lt;angry/>
.split(",")
.pump("<tr>\n","strip",String.fpM("101"," <td>","</td>\n"))+"</tr>\n"
}) + "</table>";
html.println();

The pump method writes or appends to a sink, in this case a string (eg "<table/>"). The fpM method is function/partial application and takes a string (ones and zeros) to indicate the positional input parameters. So String.fpM("101","a","c")("B") creates a new string "aBc".

Output:
Character Speech
The multitude The messiah! Show us the messiah!
Brians mother <angry>Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!</angry>
The multitude Who are you
Brians mother I'm his mother; that's who!
The multitude Behold his mother! Behold his mother!
Output:
<table>
<tr>
  <td>Character</td>
  <td>Speech</td>
</tr>
<tr>
  <td>The multitude</td>
...
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox