xml2js.builder 默认不处理 null 和空对象,需显式配置 rootname、renderopts、ignoreattributes 等参数,并设置 xmldec 编码;属性与文本须分开放置,避免混用 $ 和 _;大数据量应改用 xmlbuilder2 或流式方案。

xml2js.Builder 默认不处理空对象和 null 值
直接用 new xml2js.Builder() 转换含 null 或空对象的 JS 数据,会抛出 TypeError: Cannot read property 'length' of null,或者生成意外的空标签甚至崩溃。这不是 bug,是默认配置把 null 和 undefined 当作“该字段不存在”,但底层序列化时没做防御。
实操建议:
- 始终显式配置
renderOpts和rootName,避免依赖默认行为 - 用
ignoreAttributes: false和explicitRoot: true控制结构清晰度 - 提前过滤或替换
null/undefined:比如用JSON.parse(JSON.stringify(obj))粗暴去空(仅限简单结构),或遍历替换为""
示例安全写法:
const builder = new xml2js.Builder({
rootName: 'request',
renderOpts: { pretty: true },
ignoreAttributes: false,
explicitRoot: true,
// 把 null/undefined 转成空字符串,避免崩溃
cdataProp: '__cdata', // 可选:支持 CDATA
});
属性(attributes)和文本内容(text)必须分开放置
xml2js 不允许在同一个对象层级里既用 $ 定义属性,又用 _ 或直接字符串定义文本内容——它会静默忽略 _,或把整个节点当成纯属性处理,导致 XML 文本内容丢失。
常见错误现象:传入 { tag: { $: { id: '1' }, _: 'hello' } },结果生成 <tag id="1"></tag>,而不是 <tag id="1">hello</tag>。
实操建议:
- 文本内容必须用
_键,且不能与$同级混用;若需属性 + 文本,结构必须是{ tag: { $: { ... }, _: 'text' } } - 数组元素若含属性+文本,每个子项都要独立带
$和_,不能只在外层写一次 - 避免用数字键或保留字(如
toString)作为字段名,xml2js 内部可能误判
中文字符和特殊符号需要手动设置 encoding
默认生成的 XML 没有声明 encoding,Node.js 输出到文件或 HTTP 响应时,如果含中文,常出现乱码或解析失败。xml2js 不自动注入 <?xml version="1.0" encoding="UTF-8"?> 头,也不校验内容编码。
使用场景:API 返回 XML、写入本地 .xml 文件、和 Java/.NET 系统对接。
实操建议:
- 在
Builder配置中加xmldec: { version: '1.0', encoding: 'UTF-8', standalone: true } - 确保原始 JS 字符串本身就是 UTF-8 编码(Node.js 默认满足),不要先用
Buffer错误转码 - 写文件时用
fs.writeFileSync(path, xmlStr, 'utf8'),别漏掉第三个参数
错误示范:builder.buildObject(data) 直接拼接 <?xml ...?> 字符串——容易重复或格式错位。
Builder 性能弱于流式生成,大数据量慎用
xml2js.Builder 是内存一次性构建,对象越大,GC 压力越明显。10MB 以上 JS 对象转 XML 可能卡顿数秒,甚至 OOM。它不支持边序列化边输出,也无法中断或进度反馈。
性能影响:相比 xmlbuilder2 或原生 stream.Writable + 手写 SAX 式写入,Builder 内存占用高 2–3 倍,CPU 时间多 30%+。
实操建议:
- 单次生成 XML 不超过 1MB,数据结构扁平(嵌套 ≤ 5 层)才用
Builder - 需高频/大体积生成时,换
xmlbuilder2(API 类似,但支持流、更轻、无运行时依赖) - 若只是补全已有 XML 片段,用模板字符串或
String.raw更快更可控
容易被忽略的是:Builder 的 renderOpts.pretty 在大数据下会显著拖慢速度,上线前务必关掉。










