CSV to HTML translation: Difference between revisions
Content added Content deleted
(Add Jsish, put Julia entry back into alphabetical order) |
(Add a Python solution which makes proper use of the Python standard library and generates semantically proper HTML) |
||
Line 4,356: | Line 4,356: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
(Note: rendered versions of |
(Note: rendered versions of all three outputs are shown at the foot of this section). |
||
===Simple solution=== |
===Simple solution=== |
||
<lang python>csvtxt = '''\ |
<lang python>csvtxt = '''\ |
||
Line 4,442: | Line 4,442: | ||
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR></TBODY> |
<TBODY bgcolor="orange"><TR><TD>The multitude</TD><TD>Behold his mother! Behold his mother!</TD></TR></TBODY> |
||
</TABLE></lang> |
</TABLE></lang> |
||
===Robust solution=== |
|||
This solution uses the CSV parser and HTML-capable XML serializer included in the Python standard library to produce the same fancy table as in the "extra credit" version. |
|||
Since the version of ElementTree in the standard library does not support pretty-printing, the output it produces is minified. Unlike the "extra credit" version, this doesn't put each <code><TR></code> element in its own <code><TBODY></code>. |
|||
<lang python>from csv import DictReader |
|||
from xml.etree import ElementTree as ET |
|||
def csv2html_robust(txt, header=True, attr=None): |
|||
# Use DictReader because, despite what the docs say, reader() doesn't |
|||
# return an object with .fieldnames |
|||
# (DictReader expects an iterable that returns lines, so split on \n) |
|||
reader = DictReader(txt.split('\n')) |
|||
table = ET.Element("TABLE", **attr.get('TABLE', {})) |
|||
thead_tr = ET.SubElement( |
|||
ET.SubElement(table, "THEAD", **attr.get('THEAD', {})), |
|||
"TR") |
|||
tbody = ET.SubElement(table, "TBODY", **attr.get('TBODY', {})) |
|||
if header: |
|||
for name in reader.fieldnames: |
|||
ET.SubElement(thead_tr, "TD").text = name |
|||
for row in reader: |
|||
tr_elem = ET.SubElement(tbody, "TR", **attr.get('TR', {})) |
|||
# Use reader.fieldnames to query `row` in the correct order. |
|||
# (`row` isn't an OrderedDict prior to Python 3.6) |
|||
for field in reader.fieldnames: |
|||
td_elem = ET.SubElement(tr_elem, "TD", **attr.get('TD', {})) |
|||
td_elem.text = row[field] |
|||
return ET.tostring(table, method='html') |
|||
htmltxt = csv2html_robust(csvtxt, True, { |
|||
'TABLE': {'border': "1", 'summary': "csv2html extra program output"}, |
|||
'THEAD': {'bgcolor': "yellow"}, |
|||
'TBODY': {'bgcolor': "orange"} |
|||
}) |
|||
print(htmltxt.decode('utf8'))</lang> |
|||
'''Sample HTML output''' |
|||
<!-- |
|||
The only difference between this and The output is semantically identical to the "extra credit" version, but whitespace has been collapsed as if it had been run through a minifier. |
|||
--> |
|||
<lang html5><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><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></TBODY></TABLE></lang> |
|||
===HTML outputs rendered in firefox browser=== |
===HTML outputs rendered in firefox browser=== |