Chuyển đổi CSV sang XML là gì?
Chuyển đổi CSV sang XML là quá trình biến đổi các giá trị phân tách bằng dấu phẩy thành tài liệu Ngôn ngữ Đánh dấu Mở rộng (XML). Mỗi hàng trong CSV trở thành một phần tử XML, và mỗi tiêu đề cột ánh xạ thành tên thẻ phần tử con. Kết quả là một tài liệu phân cấp, tự mô tả mà các hệ thống có thể xác thực theo lược đồ (XSD hoặc DTD) và xử lý bằng các công cụ XML tiêu chuẩn như XSLT, XPath, và bộ phân tích SAX/DOM.
XML đã là tiêu chuẩn trao đổi dữ liệu từ khi W3C công bố đặc tả XML 1.0 vào năm 1998. Mặc dù JSON đã thay thế XML trong nhiều API web, XML vẫn là định dạng bắt buộc cho các dịch vụ web SOAP, nguồn cấp RSS/Atom, đồ họa SVG, tài liệu Office Open XML (.docx, .xlsx), tệp tài nguyên Android, cấu hình build Maven/Gradle, và các ngành được quản lý như y tế (HL7 CDA), tài chính (FpML, XBRL), và chính phủ (NIEM). Khi dữ liệu nguồn của bạn là bảng tính hoặc xuất từ cơ sở dữ liệu, chuyển đổi CSV sang XML là cách đưa dữ liệu vào các hệ thống này.
Một bộ chuyển đổi CSV sang XML đúng phải xử lý các trường hợp biên của RFC 4180: trường được trích dẫn chứa dấu phẩy hoặc ký tự xuống dòng, dấu ngoặc kép thoát, và các ký tự phân tách khác nhau. Về phía XML, nó phải thoát năm thực thể XML được định nghĩa sẵn (& < > " '), tạo tên phần tử hợp lệ từ tiêu đề (thay thế khoảng trắng và ký tự đặc biệt), và tạo ra đầu ra chuẩn với khai báo XML phù hợp và mã hóa nhất quán.
Tại sao sử dụng công cụ chuyển đổi CSV sang XML?
Viết XML thủ công từ dữ liệu bảng tính rất chậm và dễ xảy ra lỗi. Thiếu thẻ đóng hoặc quên thoát ký hiệu & sẽ tạo ra XML không hợp lệ, làm hỏng bộ phân tích phía sau. Công cụ này xử lý việc phân tích, thoát ký tự và tạo phần tử trong một bước duy nhất.
Các trường hợp sử dụng CSV sang XML
Tài liệu tham khảo ánh xạ CSV sang XML
Hiểu cách mỗi phần của tệp CSV ánh xạ sang cấu trúc XML giúp bạn dự đoán định dạng đầu ra và điều chỉnh dữ liệu trước khi chuyển đổi.
| Khái niệm CSV | Tương đương XML | Chi tiết |
|---|---|---|
| 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 so với XML
CSV là định dạng phẳng dựa trên ký tự phân tách, không có lược đồ hay kiểu dữ liệu tích hợp. XML là ngôn ngữ đánh dấu phân cấp, tự mô tả, hỗ trợ lược đồ, không gian tên và lồng nhau phức tạp. Việc lựa chọn giữa hai định dạng phụ thuộc vào yêu cầu của hệ thống downstream.
Ví dụ mã lệnh
Dưới đây là các ví dụ thực tế về chuyển đổi CSV sang XML bằng các ngôn ngữ khác nhau. Mỗi ví dụ phân tích hàng tiêu đề CSV làm tên thẻ phần tử, bọc mỗi hàng dữ liệu trong phần tử chứa, và thoát các thực thể XML trong nội dung ô.
// 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