CSV to HTML translation: Difference between revisions

From Rosetta Code
Content added Content deleted
(added ocaml)
(Python's "Sample (rendered) HTML output", trying with <nowiki>, but does not render the HTML)
Line 149: Line 149:


'''Sample (rendered) HTML output'''
'''Sample (rendered) HTML output'''
<lang html><TABLE summary="csv2html program output">
<nowiki><TABLE summary="csv2html program output">
<TBODY><TR><TD>Character</TD><TD>Speech</TD></TR></TBODY>
<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>The multitude</TD><TD>The messiah! Show us the messiah!</TD></TR></TBODY>
Line 156: Line 156:
<TBODY><TR><TD>Brians mother</TD><TD>I'm his mother; that's who!</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>
<TBODY><TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR></TBODY>
</TABLE></lang>
</TABLE></nowiki>


===Extra credit solution===
===Extra credit solution===

Revision as of 14:15, 13 November 2010

CSV to HTML translation is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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.

OCaml

<lang ocaml>let csv_data = "\ Character,Speach 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!"

(* some utility functions *)

let string_of_char = String.make 1 ;;

let string_of_string_list sl =

 List.fold_left (fun s cat -> s ^ cat) "" sl

let char_list_of_string str =

 let lst = ref [] in
 String.iter (fun c -> lst := c :: !lst) str;
 (List.rev !lst)

(** escape chars that need to be escaped *) let escape str =

 let chars = char_list_of_string str in
 let rec aux acc = function
 | [] -> (List.rev acc)
 | c :: tl ->
     match c with
     | 'A'..'Z'
     | 'a'..'z'
     | '0'..'9'
     | ' ' | ';' | '!' | '?' ->
         aux ((string_of_char c)::acc) tl
     | c ->
         let esc_char = (Printf.sprintf "&#%04d;" (Char.code c)) in
         aux (esc_char::acc) tl
 in
 string_of_string_list (aux [] chars)

(* now the main part *)

let html_table_of_csv_data ~csv_data:s =

 let len = String.length s in
 let rec aux acc_line acc i j =
   if i = len then List.rev (acc_line::acc) else
     match csv_data.[i] with
     | ',' ->
         let sub = String.sub s (j+1) (i - j - 1) in
         aux (sub::acc_line) acc (succ i) (succ i)
     | '\n' ->
         let sub = String.sub s j (i - j) in
         let acc_line = List.rev (escape sub::acc_line) in
         aux [] (acc_line::acc) (succ i) i
     | _ ->
         aux acc_line acc (succ i) j
 in
 aux [] [] 0 (-1)

let print_table segments =

print_string "

\n"; List.iter (fun line -> print_string "\n"; List.iter (Printf.printf " ") line; print_string "\n\n"; ) segments; print_string "
%s

\n";

let () =

 let segments = html_table_of_csv_data ~csv_data in
 print_table segments</lang>

Sample html output:

<lang html>

Character Speach
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

</lang>

Python

Simple solution

<lang python>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 ('' + .join('%s' % data for data in cols) + '') def csv2html(txt): htmltxt = '

\n' for rownum, row in enumerate(txt.split('\n')): htmlrow = _row2tr(row) htmlrow = ' <TBODY>%s</TBODY>\n' % htmlrow htmltxt += htmlrow htmltxt += '

\n'

   return htmltxt

htmltxt = csv2html(csvtxt) print(htmltxt)</lang>

Sample (rendered) 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><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>

Extra credit solution

<lang python>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' % (attr_td, data) for data in cols) + '') 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 += '\n'

   return htmltxt

htmltxt = csv2htmlextra(csvtxt, True,

                       dict(TABLE=' border="1" summary="csv2html extra program output"',
                            THEAD=' bgcolor="yellow"',
                            TBODY=' bgcolor="orange"' 
                            )
                       )

print(htmltxt)</lang>

Sample HTML output

<lang html>

<THEAD bgcolor="yellow"></THEAD> <TBODY bgcolor="orange"></TBODY> <TBODY bgcolor="orange"></TBODY> <TBODY bgcolor="orange"></TBODY> <TBODY bgcolor="orange"></TBODY> <TBODY bgcolor="orange"></TBODY>
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!

</lang>