CSV→HTMLテーブル変換
CSVをHTMLテーブルに変換します
CSV入力
HTML出力
CSVからHTMLテーブルへの変換とは?
CSVからHTMLテーブルへの変換は、カンマ区切りの値を、ブラウザが視覚的なテーブルとして表示できる構造化されたHTMLマークアップに変換する処理です。出力にはHTML Living Standardで定義された標準的なHTMLテーブル要素を使用します:<table>、<thead>、<tbody>、<tr>、<th>、<td>。このプロセスではCSVの各行を<tr>要素にマッピングし、各フィールドを<td>または<th>セルにマッピングします。
CSVファイルはデータをプレーンテキストとして保存し、行は改行で区切られ、フィールドは区切り文字(通常はカンマ)で区切られます。CSVはExcel・Google Sheets・データベースなどのアプリケーション間でのデータ保存と転送に適していますが、表示層を持ちません。HTMLテーブルはデータをセマンティックなマークアップで囲むことでこの表示層を追加し、CSSによるスタイリング・JavaScriptによる並べ替え・scopeやaria-labelなどの属性によるアクセシビリティをサポートします。
変換処理ではRFC 4180で定義されたいくつかのエッジケースを処理する必要があります:カンマや改行を含むクォートフィールド、フィールド内のダブルクォートのエスケープ、セミコロン・タブ・パイプなど様々な区切り文字の扱いです。正しいコンバーターはセルの内容のHTMLエンティティもエスケープし、<、>、&、クォート文字をエンティティ表現に変換することで、マークアップの破損やXSS脆弱性を防ぎます。
CSVからHTMLテーブルへのコンバーターを使う理由
HTMLテーブルを手作業で書くのは手間がかかりミスが起きやすい作業です。特に数十列・数百行のデータセットでは顕著です。このコンバーターは解析・エスケープ・整形を1ステップで処理します。
CSVからHTMLテーブルへの変換ユースケース
HTMLテーブル要素リファレンス
適切に構造化されたHTMLテーブルは、ヘッダー・本文・フッターを分離するセマンティック要素を使用します。スクリーンリーダーと検索エンジンはこれらの要素を使用してテーブルの構造を理解します。thead・tbody・tfootで行をグループ化することで、ブラウザは独立したスクロールを適用し、印刷時にヘッダー行を繰り返すことができます。
| 要素 | 役割 | 備考 |
|---|---|---|
| <table> | Table root | Wraps the entire table structure |
| <thead> | Header group | Contains header rows; browsers repeat on print page breaks |
| <tbody> | Body group | Contains data rows; enables independent scrolling with CSS |
| <tfoot> | Footer group | Summary or totals row; renders after tbody |
| <tr> | Table row | Groups cells horizontally |
| <th> | Header cell | Bold and centered by default; supports scope attribute for accessibility |
| <td> | Data cell | Standard content cell; accepts any inline or block HTML |
| <caption> | Table caption | Visible title above the table; read by screen readers first |
| <colgroup> | Column group | Applies width or style to entire columns without per-cell classes |
CSV vs HTMLテーブル
CSVはシンプルさを重視したデータ転送フォーマットですが、HTMLはブラウザでのレンダリング・アクセシビリティ・インタラクティビティを重視した表示フォーマットです。
コード例
以下は各言語でCSVをHTMLテーブルにプログラム的に変換する方法です。各例ではヘッダー行を別途処理し、セルの内容のHTMLエンティティをエスケープしています。これらのコードはスクリプト・ビルドパイプライン・データエクスポートからHTMLレポートを生成するバックエンドAPIエンドポイントにそのまま組み込めます。
// CSV string → HTML table with thead/tbody
const csv = `name,age,city
Alice,30,Berlin
Bob,25,Tokyo`
function csvToHtmlTable(csv) {
const rows = csv.trim().split('\n').map(r => r.split(','))
const [headers, ...data] = rows
const ths = headers.map(h => `<th>${h}</th>`).join('')
const trs = data.map(row =>
' <tr>' + row.map(c => `<td>${c}</td>`).join('') + '</tr>'
).join('\n')
return `<table>
<thead><tr>${ths}</tr></thead>
<tbody>
${trs}
</tbody>
</table>`
}
console.log(csvToHtmlTable(csv))
// → <table><thead><tr><th>name</th>...</tr></thead><tbody>...</tbody></table>import csv, io, html
csv_string = """name,age,city
Alice,30,Berlin
Bob,25,Tokyo"""
reader = csv.reader(io.StringIO(csv_string))
headers = next(reader)
lines = ['<table>', ' <thead>', ' <tr>']
for h in headers:
lines.append(f' <th>{html.escape(h)}</th>')
lines += [' </tr>', ' </thead>', ' <tbody>']
for row in reader:
lines.append(' <tr>')
for cell in row:
lines.append(f' <td>{html.escape(cell)}</td>')
lines.append(' </tr>')
lines += [' </tbody>', '</table>']
print('\n'.join(lines))
# → well-formed HTML table with escaped special characters<?php
$csv = "name,age,city\nAlice,30,Berlin\nBob,25,Tokyo";
$rows = array_map('str_getcsv', explode("\n", trim($csv)));
$headers = array_shift($rows);
echo "<table>\n <thead>\n <tr>\n";
foreach ($headers as $h) {
echo " <th>" . htmlspecialchars($h) . "</th>\n";
}
echo " </tr>\n </thead>\n <tbody>\n";
foreach ($rows as $row) {
echo " <tr>\n";
foreach ($row as $cell) {
echo " <td>" . htmlspecialchars($cell) . "</td>\n";
}
echo " </tr>\n";
}
echo " </tbody>\n</table>";
// → <table><thead>...<th>name</th>...</thead><tbody>...</tbody></table># Using awk — quick one-liner for simple CSV (no quoted fields)
awk -F, 'NR==1{print "<table><thead><tr>";for(i=1;i<=NF;i++)print "<th>"$i"</th>";print "</tr></thead><tbody>"}
NR>1{print "<tr>";for(i=1;i<=NF;i++)print "<td>"$i"</td>";print "</tr>"}
END{print "</tbody></table>"}' data.csv
# Using Python one-liner for RFC 4180-compliant parsing
python3 -c "
import csv, sys, html
r=csv.reader(sys.stdin); h=next(r)
print('<table><thead><tr>')
print(''.join(f'<th>{html.escape(c)}</th>' for c in h))
print('</tr></thead><tbody>')
for row in r:
print('<tr>'+''.join(f'<td>{html.escape(c)}</td>' for c in row)+'</tr>')
print('</tbody></table>')
" < data.csv