Reputation: 2704
Currently, I'm receiving an API request that has the crazy structure to the data, I'm attempting to parse the XML part of the response to an array/JSON so I can handle it.
Here's the exact request I am receiving:
{
username: 'test',
apiaccesskey: 'aa7a8157-3c17-4b63-806f-7aeff42ae21f',
action: 'placeimeiorder',
requestformat: 'JSON',
parameters:
'<PARAMETERS><CUSTOMFIELD>bnVsbA==</CUSTOMFIELD><ID>1</ID><SERVICEID>1</SERVICEID><IMEI>12345678910</IMEI><QNT>1</QNT><SERVER>0</SERVER><MODELID></MODELID><PROVIDERID></PROVIDERID><NETWORK></NETWORK><PIN></PIN><KBH></KBH><MEP></MEP><PRD></PRD><TYPE></TYPE><LOCKS></LOCKS><REFERENCE></REFERENCE><SN></SN><SECRO></SECRO></PARAMETERS>\n',
version: '7.2'
}
I've tried parsing using this library (xml2js) but it's generating a result like this:
let parseresult = await parser.parseStringPromise(req.body.parameters);
console.log(parseresult);
{ PARAMETERS:
{ CUSTOMFIELD: [ 'bnVsbA==' ],
ID: [ '1' ],
SERVICEID: [ '1' ],
IMEI: [ '12345678910' ],
QNT: [ '1' ],
SERVER: [ '0' ],
MODELID: [ '' ],
PROVIDERID: [ '' ],
NETWORK: [ '' ],
PIN: [ '' ],
KBH: [ '' ],
MEP: [ '' ],
PRD: [ '' ],
TYPE: [ '' ],
LOCKS: [ '' ],
REFERENCE: [ '' ],
SN: [ '' ],
SECRO: [ '' ] } }
which is far from ideal when trying to handle, how could I change it so I could simply access individual key/values like parseresult.IMEI
or parseresult.CUSTOMFIELD
Upvotes: 0
Views: 241
Reputation: 7237
you can also use camaro, a xpath-powered template to transform the value. it looks like this
const { transform } = require('camaro')
const data = {
username: 'test',
apiaccesskey: 'aa7a8157-3c17-4b63-806f-7aeff42ae21f',
action: 'placeimeiorder',
requestformat: 'JSON',
parameters:
'<PARAMETERS><CUSTOMFIELD>bnVsbA==</CUSTOMFIELD><ID>1</ID><SERVICEID>1</SERVICEID><IMEI>12345678910</IMEI><QNT>1</QNT><SERVER>0</SERVER><MODELID></MODELID><PROVIDERID></PROVIDERID><NETWORK></NETWORK><PIN></PIN><KBH></KBH><MEP></MEP><PRD></PRD><TYPE></TYPE><LOCKS></LOCKS><REFERENCE></REFERENCE><SN></SN><SECRO></SECRO></PARAMETERS>\n',
version: '7.2',
}
async function main() {
console.log(await transform(data.parameters, {
customerField: 'PARAMETERS/CUSTOMFIELD',
customerId: 'PARAMETERS/ID',
serviceId: 'PARAMETERS/SERVICEID',
}));
}
main()
output
{ customerField: 'bnVsbA==', customerId: '1', serviceId: '1' }
If you want more fields, you can just edit the template
Upvotes: 0
Reputation: 163352
If you want complete control over the conversion, try saxon-js (released on Node.js a couple of weeks ago, available from npm).
For example you could do it in XPath 3.1 like this:
const SaxonJS = require("saxon-js");
SaxonJS.getResource({text:xml, type:"xml"})
.then(doc => {
SaxonJS.serialize(
SaxonJS.XPath.evaluate(
"map:merge(/PARAMETERS/* ! map{name(): string()})", doc),
{method:"json", indent:true}))});
You could extend this, for example to select which fields of the XML to include in the result.
Or for even more flexibility, you could do it in XSLT3.
(Not tested.)
Upvotes: 0
Reputation: 1184
Should just be a setting.
Code:
const xml2js = require('xml2js');
const parser = new xml2js.Parser({ explicitArray: false });
const xml = "<PARAMETERS><CUSTOMFIELD>bnVsbA==</CUSTOMFIELD><ID>1</ID><SERVICEID>1</SERVICEID><IMEI>12345678910</IMEI><QNT>1</QNT><SERVER>0</SERVER><MODELID></MODELID><PROVIDERID></PROVIDERID><NETWORK></NETWORK><PIN></PIN><KBH></KBH><MEP></MEP><PRD></PRD><TYPE></TYPE><LOCKS></LOCKS><REFERENCE></REFERENCE><SN></SN><SECRO></SECRO></PARAMETERS>\n";
parser.parseString(xml, (err, result) => {
console.dir(result);
});
Reference: https://github.com/Leonidas-from-XIV/node-xml2js#options
Output:
{
PARAMETERS: {
CUSTOMFIELD: 'bnVsbA==',
ID: '1',
SERVICEID: '1',
IMEI: '12345678910',
QNT: '1',
SERVER: '0',
MODELID: '',
PROVIDERID: '',
NETWORK: '',
PIN: '',
KBH: '',
MEP: '',
PRD: '',
TYPE: '',
LOCKS: '',
REFERENCE: '',
SN: '',
SECRO: ''
}
}
Alternative: Using the async/await like you have above:
const xml2js = require('xml2js');
(async () => {
const parser = new xml2js.Parser({ explicitArray: false });
const xml = "<PARAMETERS><CUSTOMFIELD>bnVsbA==</CUSTOMFIELD><ID>1</ID><SERVICEID>1</SERVICEID><IMEI>12345678910</IMEI><QNT>1</QNT><SERVER>0</SERVER><MODELID></MODELID><PROVIDERID></PROVIDERID><NETWORK></NETWORK><PIN></PIN><KBH></KBH><MEP></MEP><PRD></PRD><TYPE></TYPE><LOCKS></LOCKS><REFERENCE></REFERENCE><SN></SN><SECRO></SECRO></PARAMETERS>\n";
try {
console.log(await parser.parseStringPromise(xml))
} catch (error) {
console.log('ERROR', error);
}
})();
Upvotes: 1