Node.js使用xml-to-json-promise移除JSON键名p:前缀问题
解决xml-to-json-promise转换后键名带命名空间前缀的问题
我之前也碰到过XML转JSON时命名空间前缀残留的问题,刚好能给你两个实用的解决思路,毕竟不能修改原XML的话,只能从转换环节或者后续处理入手:
方法一:利用模块内置配置直接移除前缀
xml-to-json-promise其实是基于xml2js封装的,而xml2js本身提供了移除命名空间前缀的配置项stripPrefix。你只需要在转换时传入对应的配置就能自动处理:
const xmlToJson = require('xml-to-json-promise'); async function convertXml() { // 替换成你的XML字符串 const xmlContent = `<?xml version="1.0" encoding="utf-8"?> <p:Order xmlns:p="http://no.lyse.ikt.altisalg.Order" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="filename.xsd" source="AltiSalg 2.4.4-IB-154-IB-154 (154)"><p:Customer><p:OrderId></p:OrderId> <p:FirstName></p:FirstName> <p:LastName></p:LastName> <p:EmailAddress></p:EmailAddress> <p:BirthDate></p:BirthDate> <p:CellularPhone></p:CellularPhone> <p:City></p:City> <p:Country></p:Country> <p:PostalCode></p:PostalCode> <p:StreetAddress></p:StreetAddress> <p:PartnerId></p:PartnerId> <p:CommunicationPreferences><p:Phone></p:Phone> <p:Email></p:Email> <p:Mail></p:Mail> <p:SMS></p:SMS> </p:CommunicationPreferences> <p:ServiceAgreement><p:AgreementType></p:AgreementType> <p:AgreementStartDate></p:AgreementStartDate> <p:AgreementStatus></p:AgreementStatus> <p:Comment></p:Comment> <p:ListOfAssets><p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> </p:ListOfAssets> </p:ServiceAgreement> </p:Customer> </p:Order>`; const options = { xml2js: { stripPrefix: true, // 核心配置:一键移除所有命名空间前缀 ignoreAttrs: true, // 可选:如果不需要保留XML里的属性(比如xmlns、source这些)可以开启 explicitArray: false // 可选:避免单个元素被强制包装成数组,按需调整 } }; const jsonResult = await xmlToJson(xmlContent, options); // 现在jsonResult里的键都是不带p:前缀的了,比如jsonResult.Order.Customer console.log(jsonResult.Order.Customer.FirstName); } convertXml();
这个方法最省心,直接借助底层库的能力搞定,不用自己写额外的处理逻辑。
方法二:手动递归清理键名前缀(兼容所有情况)
如果因为版本问题或者其他原因,模块的配置没生效,那就写个递归函数遍历整个JSON对象,把所有带p:的键名替换掉:
const xmlToJson = require('xml-to-json-promise'); // 递归处理所有层级的键名 function stripNamespacePrefix(obj) { // 处理数组 if (Array.isArray(obj)) { return obj.map(item => stripNamespacePrefix(item)); } // 处理对象 if (typeof obj === 'object' && obj !== null) { const cleanedObj = {}; for (const [key, value] of Object.entries(obj)) { // 去掉键名开头的p:前缀 const newKey = key.replace(/^p:/, ''); cleanedObj[newKey] = stripNamespacePrefix(value); } return cleanedObj; } // 基础类型直接返回 return obj; } async function convertAndClean() { // 替换成你的XML字符串 const xmlContent = `<?xml version="1.0" encoding="utf-8"?> <p:Order xmlns:p="http://no.lyse.ikt.altisalg.Order" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="filename.xsd" source="AltiSalg 2.4.4-IB-154-IB-154 (154)"><p:Customer><p:OrderId></p:OrderId> <p:FirstName></p:FirstName> <p:LastName></p:LastName> <p:EmailAddress></p:EmailAddress> <p:BirthDate></p:BirthDate> <p:CellularPhone></p:CellularPhone> <p:City></p:City> <p:Country></p:Country> <p:PostalCode></p:PostalCode> <p:StreetAddress></p:StreetAddress> <p:PartnerId></p:PartnerId> <p:CommunicationPreferences><p:Phone></p:Phone> <p:Email></p:Email> <p:Mail></p:Mail> <p:SMS></p:SMS> </p:CommunicationPreferences> <p:ServiceAgreement><p:AgreementType></p:AgreementType> <p:AgreementStartDate></p:AgreementStartDate> <p:AgreementStatus></p:AgreementStatus> <p:Comment></p:Comment> <p:ListOfAssets><p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> <p:Asset><p:ProductPartNumber></p:ProductPartNumber> <p:Comments></p:Comments> </p:Asset> </p:ListOfAssets> </p:ServiceAgreement> </p:Customer> </p:Order>`; // 先拿到原始转换后的JSON const rawJson = await xmlToJson(xmlContent); // 清理前缀 const cleanedJson = stripNamespacePrefix(rawJson); // 现在可以正常访问了 console.log(cleanedJson.Order.Customer.EmailAddress); } convertAndClean();
这个函数能处理所有嵌套结构,不管是对象里套对象,还是数组里的元素,都能把所有p:前缀去掉,兼容性拉满。
转换后的效果示例
处理后的JSON结构会变成这样(简化版):
{ "Order": { "Customer": { "OrderId": "", "FirstName": "", "LastName": "", "CommunicationPreferences": { "Phone": "", "Email": "" }, "ServiceAgreement": { "ListOfAssets": [ {"ProductPartNumber": "", "Comments": ""}, {"ProductPartNumber": "", "Comments": ""} ] } } } }
这样你就可以直接通过常规的对象属性访问方式操作这些字段了。
内容的提问来源于stack exchange,提问作者Pritesh Mahajan
相关产品推荐
相关产品推荐

