在企业数据交互、旧系统迁移等场景中,经常需要将存储扁平化数据的CSV文件转换为符合特定规范的XML格式,满足下游系统的数据接收要求。实现这个转换的核心是理清CSV字段和目标XML节点之间的对应关系,再按照XML语法规则生成文件。

前期准备:明确输入输出结构
首先需要明确两个关键结构:源CSV的字段定义,以及目标XML的节点层级和标签名称。假设我们有一个存储用户信息的CSV文件user.csv,内容如下:
id,name,age,email 1001,张三,25,zhangsan@ipipp.com 1002,李四,28,lisi@ipipp.com
目标XML格式要求每个用户作为user节点,子节点对应CSV的字段,同时外层包裹users根节点,结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user>
<id>1001</id>
<name>张三</name>
<age>25</age>
<email>zhangsan@ipipp.com</email>
</user>
<user>
<id>1002</id>
<name>李四</name>
<age>28</age>
<email>lisi@ipipp.com</email>
</user>
</users>
核心实现步骤
1. 读取CSV文件数据
使用Python内置的csv模块读取CSV内容,将表头和数据行分离,方便后续映射。代码如下:
import csv
def read_csv(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
# 读取CSV内容,第一行为表头
reader = csv.reader(f)
headers = next(reader)
data_rows = [row for row in reader]
return headers, data_rows
# 调用函数读取文件
csv_headers, csv_data = read_csv('user.csv')
print("CSV表头:", csv_headers)
print("CSV数据行:", csv_data)
2. 构建XML映射规则
根据目标XML的节点名称,建立CSV表头到XML标签的映射字典,避免硬编码标签名称,方便后续修改规则。映射关系如下:
| CSV表头 | XML标签名 |
|---|---|
| id | id |
| name | name |
| age | age |
对应的Python映射字典代码:
# 映射规则:key为CSV表头,value为对应的XML标签名
xml_mapping = {
'id': 'id',
'name': 'name',
'age': 'age',
'email': 'email'
}
3. 生成目标XML文件
使用xml.etree.ElementTree模块构建XML树,按照映射规则将CSV数据填充到对应的XML节点中,最后写入文件。完整代码如下:
import xml.etree.ElementTree as ET
def csv_to_xml(csv_path, xml_path, mapping):
# 读取CSV数据
headers, data_rows = read_csv(csv_path)
# 创建根节点
root = ET.Element('users')
# 遍历每一行CSV数据
for row in data_rows:
# 创建user子节点
user_node = ET.SubElement(root, 'user')
# 遍历当前行的每个字段,按照映射规则生成子节点
for i in range(len(headers)):
header = headers[i]
value = row[i]
# 获取当前字段对应的XML标签名
tag_name = mapping.get(header)
if tag_name:
# 创建子节点并赋值
child_node = ET.SubElement(user_node, tag_name)
child_node.text = value
# 生成XML树并写入文件
tree = ET.ElementTree(root)
# 设置xml声明
ET.indent(tree, space=" ")
tree.write(xml_path, encoding='utf-8', xml_declaration=True)
# 执行转换
csv_to_xml('user.csv', 'user.xml', xml_mapping)
特殊场景处理
CSV字段对应XML属性而非子节点
如果目标XML要求部分CSV字段作为节点的属性,比如<user id="1001" name="张三">,只需要修改节点生成逻辑即可:
def csv_to_xml_with_attr(csv_path, xml_path, mapping):
headers, data_rows = read_csv(csv_path)
root = ET.Element('users')
for row in data_rows:
user_node = ET.SubElement(root, 'user')
for i in range(len(headers)):
header = headers[i]
value = row[i]
tag_name = mapping.get(header)
if tag_name:
# 将CSV字段作为user节点的属性
user_node.set(tag_name, value)
tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
tree.write(xml_path, encoding='utf-8', xml_declaration=True)
处理带嵌套结构的XML
如果目标XML存在多层嵌套,比如user下还有contact子节点包裹email,可以在映射规则中定义层级关系,生成时先创建父节点再添加子节点即可。
注意事项
- CSV文件编码需要和读取时指定的编码一致,避免出现乱码问题
- 生成的XML标签名需要符合XML命名规范,不能以数字开头,不能包含空格和特殊字符
- 如果CSV中存在特殊字符比如
<、>,需要在生成XML时进行转义,避免破坏XML结构 - 批量处理大文件时,建议逐行读取CSV和逐行生成XML,避免占用过多内存
本文的示例代码基于Python实现,其他语言如Java、PHP的实现逻辑类似,核心都是读取CSV、建立映射、拼接生成XML字符串或对象,最终输出文件。