CSV เป็น XML คืออะไร?
การแปลง CSV เป็น XML คือกระบวนการเปลี่ยนข้อมูลที่คั่นด้วยจุลภาคให้กลายเป็นเอกสาร Extensible Markup Language (XML) แต่ละแถวของ CSV จะกลายเป็น XML element และแต่ละหัวคอลัมน์จะกลายเป็นชื่อ child element tag ผลลัพธ์คือเอกสารแบบลำดับชั้นที่อธิบายตัวเองได้ ซึ่งระบบต่าง ๆ สามารถตรวจสอบด้วย schema (XSD หรือ DTD) และประมวลผลด้วยเครื่องมือ XML มาตรฐาน เช่น XSLT, XPath และ SAX/DOM parsers
XML เป็นมาตรฐานการแลกเปลี่ยนข้อมูลมาตั้งแต่ปี 1998 ที่ W3C เผยแพร่ข้อกำหนด XML 1.0 แม้ว่า JSON จะเข้ามาแทนที่ XML ใน web API จำนวนมาก แต่ XML ยังคงเป็นรูปแบบที่จำเป็นสำหรับ SOAP web services, RSS/Atom feeds, SVG graphics, Office Open XML documents (.docx, .xlsx), Android resource files, Maven/Gradle build configs และอุตสาหกรรมที่มีการควบคุม เช่น สาธารณสุข (HL7 CDA), การเงิน (FpML, XBRL) และภาครัฐ (NIEM) เมื่อข้อมูลต้นทางเป็น spreadsheet หรือการส่งออกจากฐานข้อมูล การแปลง CSV เป็น XML คือวิธีนำข้อมูลเข้าสู่ระบบเหล่านี้
เครื่องมือแปลง CSV เป็น XML ที่ถูกต้องต้องรองรับ edge cases ตาม RFC 4180 ได้แก่ ฟิลด์ที่ใส่เครื่องหมายคำพูดซึ่งมีจุลภาคหรือขึ้นบรรทัดใหม่ เครื่องหมายคำพูดคู่ที่ escape แล้ว และตัวคั่นที่หลากหลาย ในส่วนของ XML ต้องทำการ escape ห้า XML entities ที่กำหนดไว้ล่วงหน้า (& < > " ') สร้างชื่อ element ที่ถูกต้องจากหัวคอลัมน์ (โดยแทนที่ช่องว่างและอักขระพิเศษ) และสร้างผลลัพธ์ที่ well-formed พร้อม XML declaration และ encoding ที่สอดคล้องกัน
ทำไมต้องใช้เครื่องมือแปลง CSV เป็น XML?
การเขียน XML ด้วยมือจากข้อมูล spreadsheet ทำได้ช้าและเกิดข้อผิดพลาดได้ง่าย การลืม closing tag หรือไม่ทำการ escape เครื่องหมาย ampersand จะทำให้ XML ไม่ถูกต้องและทำให้ parser ปลายทางเกิดปัญหา เครื่องมือนี้จัดการการ parse, escape และการสร้าง element ในขั้นตอนเดียว
กรณีการใช้งานแปลง CSV เป็น XML
ตารางอ้างอิงการ mapping CSV เป็น XML
การเข้าใจว่าแต่ละส่วนของไฟล์ CSV ถูก map ไปยังโครงสร้าง XML อย่างไร ช่วยให้คุณคาดการณ์รูปแบบผลลัพธ์และปรับข้อมูลก่อนแปลงได้
| แนวคิด CSV | XML ที่เทียบเท่า | รายละเอียด |
|---|---|---|
| CSV file | XML document | The entire file maps to a root element containing all records |
| Header row | Element tag names | Each column header becomes the tag name for child elements |
| Data row | <row> element | Each row becomes a repeating child element of the root |
| Cell value | Text node | Cell content becomes the text inside the corresponding tag |
| Empty cell | Empty element or omitted | Can be rendered as <field/> or excluded from output |
| Comma delimiter | XML structure | Delimiters are replaced by element nesting and closing tags |
CSV เทียบกับ XML
CSV เป็นรูปแบบแบบแบนที่ใช้ตัวคั่นโดยไม่มี schema หรือประเภทข้อมูลในตัว XML เป็นภาษา markup แบบลำดับชั้นที่อธิบายตัวเองได้ รองรับ schemas, namespaces และการซ้อนที่ซับซ้อน การเลือกใช้รูปแบบใดขึ้นอยู่กับข้อกำหนดของระบบปลายทาง
ตัวอย่างโค้ด
ด้านล่างเป็นตัวอย่างการแปลง CSV เป็น XML ในภาษาโปรแกรมต่าง ๆ แต่ละตัวอย่างจะ parse แถวหัวคอลัมน์ของ CSV เป็นชื่อ element tag ห่อแต่ละแถวข้อมูลด้วย container element และ escape XML entities ในเนื้อหาของ cell
// CSV string → XML with proper escaping
const csv = `name,age,city
Alice,30,Berlin
Bob,25,Tokyo`
function csvToXml(csv, rootTag = 'data', rowTag = 'row') {
const rows = csv.trim().split('\n').map(r => r.split(','))
const [headers, ...data] = rows
const xmlRows = data.map(row => {
const fields = headers.map((h, i) => {
const val = (row[i] || '').replace(/&/g, '&')
.replace(/</g, '<').replace(/>/g, '>')
return ` <${h}>${val}</${h}>`
}).join('\n')
return ` <${rowTag}>\n${fields}\n </${rowTag}>`
}).join('\n')
return `<?xml version="1.0" encoding="UTF-8"?>\n<${rootTag}>\n${xmlRows}\n</${rootTag}>`
}
console.log(csvToXml(csv))
// → <?xml version="1.0" encoding="UTF-8"?>
// → <data><row><name>Alice</name><age>30</age>...</row>...</data>import csv, io
from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom.minidom import parseString
csv_string = """name,age,city
Alice,30,Berlin
Bob,25,Tokyo"""
reader = csv.DictReader(io.StringIO(csv_string))
root = Element('data')
for row in reader:
row_el = SubElement(root, 'row')
for key, value in row.items():
child = SubElement(row_el, key)
child.text = value
# Pretty-print with declaration
raw = tostring(root, encoding='unicode')
pretty = parseString(raw).toprettyxml(indent=' ')
print(pretty)
# → <?xml version="1.0" ?>
# → <data>
# → <row>
# → <name>Alice</name>
# → <age>30</age>
# → <city>Berlin</city>
# → </row>
# → ...
# → </data>package main
import (
"encoding/csv"
"encoding/xml"
"fmt"
"os"
"strings"
)
type Field struct {
XMLName xml.Name
Value string `xml:",chardata"`
}
type Row struct {
XMLName xml.Name `xml:"row"`
Fields []Field
}
type Data struct {
XMLName xml.Name `xml:"data"`
Rows []Row
}
func main() {
input := "name,age,city\nAlice,30,Berlin\nBob,25,Tokyo"
r := csv.NewReader(strings.NewReader(input))
records, _ := r.ReadAll()
headers := records[0]
var data Data
for _, rec := range records[1:] {
row := Row{}
for i, h := range headers {
row.Fields = append(row.Fields, Field{
XMLName: xml.Name{Local: h},
Value: rec[i],
})
}
data.Rows = append(data.Rows, row)
}
out, _ := xml.MarshalIndent(data, "", " ")
fmt.Println(xml.Header + string(out))
// → <?xml version="1.0" encoding="UTF-8"?>
// → <data><row><name>Alice</name>...</row>...</data>
}# Using Python's csv and xml modules via one-liner
python3 -c "
import csv, sys
from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom.minidom import parseString
reader = csv.DictReader(sys.stdin)
root = Element('data')
for row in reader:
r = SubElement(root, 'row')
for k, v in row.items():
SubElement(r, k).text = v
print(parseString(tostring(root, encoding='unicode')).toprettyxml(indent=' '))
" < data.csv
# Using Miller (mlr) — a dedicated CSV/JSON/XML tool
mlr --icsv --oxml cat data.csv