XML转SQL需先规范结构:确保平铺记录节点、合法字段名、清洗特殊字符;推荐xsltproc+XSLT或Python ElementTree,注意字符集、NULL处理及BOM清理。

XML转SQL Insert语句:先确认结构是否规整
直接拿原始XML去生成Insert,大概率失败——xml2sql、xsldoc这类工具只认“表结构明确”的XML。比如每条记录是<row>或<record>,字段用子节点或属性表示;如果嵌套三层、混合文本和属性、还有CDATA块,工具会丢字段或报错Invalid token at line X。
实操建议:
- 用浏览器或
xmllint --format input.xml先看缩进是否一致,确认根节点下是平铺的同级记录节点 - 字段名必须是合法SQL列名:避免空格、中文、以数字开头(如
<2nd_value>要重命名) - 如果XML里有
<price>¥199.00</price>这种带符号的值,得提前清洗,否则生成的INSERT会语法错误
命令行快速生成:用xsltproc + XSLT模板
比在线工具更可控,尤其适合批量处理或CI中调用。核心是写一个XSLT模板把每个row转成INSERT INTO ... VALUES (...),再用系统自带的xsltproc执行。
常见错误现象:xsltproc: failed to parse stylesheet.xsl——通常因为XSLT版本写错(用version="1.0",别写2.0)、或<xsl:value-of>里用了不支持的XPath函数(如replace())。
示例(假设XML中每条记录为<user id="1" name="Alice"/>):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/users">
<xsl:for-each select="user">INSERT INTO users (id, name) VALUES (<xsl:value-of select="@id"/>, '<xsl:value-of select="@name"/>');</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
执行命令:xsltproc template.xsl data.xml > insert.sql
Python脚本替代方案:用xml.etree.ElementTree更稳
在线工具常对大文件(>10MB)超时或截断,ElementTree在内存里解析,可控性高,还能加清洗逻辑。
容易踩的坑:
-
tree.getroot()后没检查root.tag是否符合预期,导致for child in root:循环为空 - 字段含单引号(如
O'Connor)直接拼SQL会崩,必须用value.replace("'", "''")或参数化占位(但Insert语句本身不支持预编译,只能转义) - 数值字段用
child.text取出来是字符串,插入前要int()或float(),否则生成的SQL里带引号变成字符串字面量
关键片段示意:
import xml.etree.ElementTree as ET
tree = ET.parse('data.xml')
root = tree.getroot()
for row in root.findall('row'):
id_val = row.find('id').text.strip()
name_val = row.find('name').text.replace("'", "''")
print(f"INSERT INTO t VALUES ({id_val}, '{name_val}');")
生成的SQL怎么用:注意字符集和NULL处理
生成的insert.sql直接mysql -u user db < insert.sql可能报错Incorrect string value——XML默认是UTF-8,但MySQL连接或表字符集可能是latin1。
实操要点:
- 导出前确认目标表用
utf8mb4:运行SHOW CREATE TABLE users;,看CHARSET=utf8mb4是否在建表语句里 - XML中空字段(
<age/>或<age></age>)默认生成VALUES (''),但数据库期望NULL,得在脚本里判断if elem.text is None or elem.text.strip() == ''然后输出NULL - 避免一次导入几万条:MySQL默认
max_allowed_packet=4M,大文件拆成每500条一个事务,加BEGIN;/COMMIT;包裹
最麻烦的其实是XML里混着HTML片段、换行符、BOM头——这些不会报错,但会让生成的SQL执行失败,且错误位置难定位。处理前先head -c 100 data.xml | hexdump -C看有没有ef bb bf(BOM),有就用sed -i '1s/^\xEF\xBB\xBF//' data.xml清理。









