Node.js中xml2js库的使用:XML与JS对象互转

1次阅读

xml2js.parseString() 返回 undefined 是因它是异步 API,必须传回调函数;同步解析应使用 parseStringpromise() 或 Parser 实例配合 Promise 封装

Node.js中xml2js库的使用:XML与JS对象互转

xml2js.parseString() 解析 XML 字符串为什么返回 undefined?

常见原因是没传回调函数xml2js.parseString() 是异步 API,不支持直接 return。同步解析要用 xml2js.parseStringPromise()(v0.5+)或改用 new xml2js.Parser().parseString() 配合 Promise 封装。

  • 错误写法:
    const result = xml2js.parseString(xml); // result 是 undefined
  • 正确写法(推荐 Promise 版):
    xml2js.parseStringPromise(xml)   .then(obj => console.log(obj))   .catch(err => console.error(err));
  • 若需同步行为(仅限可信、小体积 XML),可用 DOMParser + 自定义转换,但 xml2js 本身无真正同步解析入口

如何控制 parseString 的输出结构(比如去掉 $、_ 等属性)?

xml2js 默认把 XML 属性存为 $,文本内容存为 _,容易干扰后续处理。通过 options 关键参数可简化结构:

  • attrkey: '_' → 把属性统一挂到 _ 下(默认是 $
  • charkey: '#' → 把文本内容挂到 # 下(默认是 _
  • ignoreAttrs: true → 完全忽略属性(最常用)
  • explicitArray: false → 单个子元素不包装成数组(避免 [{…}]
  • 示例:
    const parser = new xml2js.Parser({   ignoreAttrs: true,   explicitArray: false,   trim: true }); parser.parseString(xml, (err, result) => { /* result 中无 $ 和 _ */ });

xml2js.Builder() 生成 XML 时中文乱码或缺少 XML 声明?

默认生成的 XML 是 UTF-8 编码字符串,但不带 声明,且若原始 JS 对象含非 ASCII 字符,需确保运行环境支持 UTF-8 输出(如 node.js 终端、文件写入时指定编码)。

  • 添加声明:传入 rootNamexmldec 选项
    const builder = new xml2js.Builder({   xmldec: { version: '1.0', encoding: 'UTF-8', standalone: true },   rootName: 'root' }); const xml = builder.buildObject(obj); // 此时开头会有 
  • 写入文件时务必用 fs.writeFileSync(path, xml, 'utf8'),否则 windows 记事本可能误判编码
  • 避免在对象字段中混用 Buffer / stream —— xml2js.Builder 只接受 plain object / array / string / number / Boolean

与 xml-js、fast-xml-parser 等库对比,什么场景该坚持用 xml2js?

xml2js 优势不在性能,而在对复杂 XML(含混合内容、命名空间、DOCTYPE、CDATA)的兼容性,以及成熟稳定的回调/Promise 接口设计。如果项目已依赖它处理带 xmlns 的 SOAP 或 RSS,贸然切换反而易出错。

  • 适合:SOAP 响应解析、遗留系统 XML 集成、需要保留注释或 CDATA 的场景
  • 不适合:大文件流式解析(用 sax)、纯性能敏感场景(用 fast-xml-parser)、需严格 XSD 校验(需额外加 libxmljs
  • 注意:xml2js v0.4.x 不支持 ESM,v0.5+ 才有 parseStringPromise;升级后需检查 BuilderrenderOpts 是否被重命名(已改为 xmldec 等)

实际用的时候,最常踩的坑不是语法,而是忘了 ignoreAttrs: true 导致对象里突然冒出一 $ 字段,或者没配 explicitArray: false,结果取 obj.items.name 报错——因为它是 obj.items[0].name。这些细节不试一次根本记不住。

text=ZqhQzanResources