XML Attribute not working in Node.js xml2js - javascript

I'm trying to parse XML with Node.js and xml2js. In the documentation is says that $ is the character to access attributes. It doesn't seem to be working in my case.
The object result.ApiResponse.CommandResponse works fine. But anything I put afterwards is undefined.
Here's my code, it says $ is undefined :
var xml2js = require('xml2js');
var util = require('util');
var parser = new xml2js.Parser();
var xml = '<ApiResponse Status="OK"><Errors/><Warnings/><RequestedCommand>namecheap.domains.check</RequestedCommand><CommandResponse Type="namecheap.domains.check"><DomainCheckResult Domain="us.xyz" Available="true" ErrorNo="0" Description="" IsPremiumName="true" PremiumRegistrationPrice="13000.0000" PremiumRenewalPrice="13000.0000" PremiumRestorePrice="65.0000" PremiumTransferPrice="13000.0000" IcannFee="0.0000" EapFee="0.0000"/></CommandResponse><Server>PHX01APIEXT01</Server><GMTTimeDifference>--5:00</GMTTimeDifference><ExecutionTime>4.516</ExecutionTime></ApiResponse>';
parser.parseString(xml, function (err, result) {
console.log(util.inspect(result.ApiResponse.CommandResponse.DomainCheckResult.$.Available, false, null))
});
Here's the console.log(result):
{ ApiResponse:
{ '$': { Status: 'OK' },
Errors: [ '' ],
Warnings: [ '' ],
RequestedCommand: [ 'namecheap.domains.check' ],
CommandResponse:
[ { '$': { Type: 'namecheap.domains.check' },
DomainCheckResult:
[ { '$':
{ Domain: 'us.xyz',
Available: 'true',
ErrorNo: '0',
Description: '',
IsPremiumName: 'true',
PremiumRegistrationPrice: '13000.0000',
PremiumRenewalPrice: '13000.0000',
PremiumRestorePrice: '65.0000',
PremiumTransferPrice: '13000.0000',
IcannFee: '0.0000',
EapFee: '0.0000' } } ] } ],
Server: [ 'PHX01APIEXT01' ],
GMTTimeDifference: [ '--5:00' ],
ExecutionTime: [ '4.516' ] } }

It looks like CommandResponse and DomainCheckResult are actually arrays, so you need to access their first elements using [0] before digging deeper into your data.
console.log(util.inspect(
result.ApiResponse.CommandResponse[0].DomainCheckResult[0].$.Available,
false, null
))

Related

Calling a JSON key that has a non-letter character

I am trying to return the value of #microsoft.graph.downloadUrl from the json object below:
[
{
'#microsoft.graph.downloadUrl': 'https://public.bl.files.1drv.com/XXXX',
createdDateTime: '2021-07-10T06:14:31.03Z',
cTag: 'QQQQ',
eTag: 'SSSS',
id: 'FFFF',
lastModifiedDateTime: '2021-07-12T09:27:21.69Z',
name: 'FILE_NAME',
size: 98580,
webUrl: 'https://1drv.ms/b/SSSS',
reactions: { commentCount: 0 },
createdBy: { application: [Object], user: [Object] },
lastModifiedBy: { user: [Object] },
parentReference: {
driveId: 'XXX',
driveType: 'personal',
id: 'YYYY!YYY',
name: 'Documents',
path: '/drive/root:/Documents'
},
file: { mimeType: 'application/pdf', hashes: [Object] },
fileSystemInfo: {
createdDateTime: '2021-07-10T06:14:31.03Z',
lastModifiedDateTime: '2021-07-12T09:27:21.69Z'
}
}
]
I wish to use something like this that i had done to extract the name as I need to be able to get the #microsoft.graph.downloadUrl from each json object (known as f below) in 'files'.
var fileName = (JSON.stringify(files[f].name));
I tried both:
var fileURL = (JSON.stringify(files[f]."#microsoft.graph.downloadUrl"));
var fileURL = (JSON.stringify(files[f].#microsoft.graph.downloadUrl));
but neither work -- any help would be much appreciated!
You should just use files[f]["#microsoft.graph.downloadUrl"].

js add object to object with $or and get [object]

I try to generate an object with {$or: [{object1}, {object2},...]} to fire a query to mongo, but I always get [object] after assigning to $or. Can somebody help me and tell me what I´m doing wrong. I tried it with creating an own array for the $or[], with a for-loop and so on - always the same. Some ideas?
if(req.body.sicDiv) {
co_sicDiv = {
$in: sicDiv.split(',')
};
query = Object.assign({co_sicDiv: co_sicDiv}, query);
//works fine, I get: { co_sicDiv: { '$in': [ 'C' ] }
}
if(req.body.sicMajor) {
if (sicDiv){
co_sicMaj = {
$in: sicMaj.split(',')
};
console.log('co_sicMaj: ', co_sicMaj);
sicMajO =Object.assign(
{'co_sicDiv': co_sicDiv},
{'co_sicMaj' : co_sicMaj}
);
console.log('SicMajO: ', sicMajO);
//Works fine, I get: SicMajO: { co_sicDiv: { '$in': [ 'C' ] }, co_sicMaj: { '$in': [ '15', '16' ] } }
sicMajOR =Object.assign({$or: [
{'co_sicDiv': co_sicDiv},
{'co_sicMaj' : co_sicMaj}
]}
);
console.log('SicMajOR: ', sicMajOR);
//Doesn´t work, I get: SicMajOR: { '$or': [ { co_sicDiv: [Object] }, { co_sicMaj: [Object] } ] }

Storing data from JSON object received from Google People Api

So I have a server that receives data from Google People api regarding contacts and my received object has the following structure:
{ connections:
[ { resourceName: 'people/c3904925882068251400',
etag: '%EgYBAgkLNy4aDQECAwQFBgcICQoLDA0iDFZUOUE0NkRBZW0wPQ==',
names:
[ { metadata: { primary: true, source: [Object] },
displayName: 'Mihai Vrincut',
familyName: 'Vrincut',
givenName: 'Mihai',
displayNameLastFirst: 'Vrincut, Mihai' },
{ metadata: { source: [Object] },
displayName: 'Mihai Vrincut',
familyName: 'Vrincut',
givenName: 'Mihai',
displayNameLastFirst: 'Vrincut, Mihai' } ],
emailAddresses:
[ { metadata: { primary: true, source: [Object] },
value: 'mihai.vrincut#gmail.com' } ] },
{ resourceName: 'people/c3275206487406036814',
etag: '%EgYBAgkLNy4aDQECAwQFBgcICQoLDA0iDHBFVzBUMm8wWU5nPQ==',
names:
[ { metadata: { primary: true, source: [Object] },
displayName: 'aaaaaaaaa',
givenName: 'aaaaaaaaa',
displayNameLastFirst: 'aaaaaaaaa' } ] },
{ resourceName: 'people/c5777943907795350059',
etag: '%EgYBAgkLNy4aDQECAwQFBgcICQoLDA0iDGxOeGYwblg3bFUwPQ==',
names:
[ { metadata: { primary: true, source: [Object] },
displayName: 'costin',
givenName: 'costin',
phoneticFamilyName: 'cancius',
phoneticGivenName: 'costin',
displayNameLastFirst: 'costin' } ],
emailAddresses: [ { metadata: { primary: true, source: [Object] }, value: 'hj' } ],
phoneNumbers:
[ { metadata: { primary: true, source: [Object] },
value: '07543532512',
canonicalForm: '+40754353251' } ] } ], totalPeople: 3}totalItems: 3 }
In order to get this object I used the util.inspect() method. However, when I try to access the names for example, I get undefined:
var response=util.inspect(responses,{depth:5});
Console.log(response.connections[0].names);
What is wrong?
So, given the situation, and the information you've given over the comment sections.
I assume that responses is already an object, but util.inspect, makes it a string with a JSON kind of syntax but without the quotes (") before and after the names of the keys. That's why you get
{ connections: ^ SyntaxError: Unexpected token c in JSON at position 2
So, try going over the responses object.
console.log(responses)
And get the name of the keys. With them
console.log(responses.sth.sthElse.anotherSth.anotherSthElse.lastSth.connections)
And see if you get the expected result :)
You should convert the response to JSON Object.
try this:
console.log(JSON.parse(response).connections[0].names);
(I am assuming you are working in Javascript)
What I would do is validate if the answer is a String, you have a
console.log (typeof response)
if it is a string, convert it to JSON:
let responseObject = JSON.parse (response);
Finally, try if you can access the object:
console.log (responseObject.connections [0] .names);
You tell me your answer :)

How to get the name of the most "root" key?

I have a js object in NodeJs application:
> req.body
{ my_root_key: { some_key2: [ [Object] ], some_key3: [ [Object] ] } }
How can I obtain the name of the most base key, in this case "my_root_key"?
Try this:
var data = { my_root_key: { some_key2: [ [Object] ], some_key3: [ [Object] ] } }
console.log(Object.keys(data)[0]);

NodeJS module - populated arrays turning into empty objects. Why?

I have a module which exports a config object:
module.exports = {
music : {
catalog : {
mysql : {
requiredFields : {
foo : [1,2,3],
trackQuery : [
{
table : 'tracks',
alias : 't',
foo : [1,2,3],
fields : [
'id',
'name',
'duration'
]
},
{
table : 'artists',
alias : 'a',
fields : [
'id',
'name'
]
}
]
}
}
}
}
}
The fields arrays are turning into empty objects at runtime.
I'm confirming like this:
var conf = require('musicConfig');
console.log ("requiredFields = %j", conf.music.catalog.mysql.requiredFields);
...which outputs this:
requiredFields = ["foo":[1,2,3],"trackQuery":[{"table":"tracks","alias":"t","foo":{},"fields":{}},{"table":"artists","alias":"a","fields":{}}]]
As you can see:
conf.music.catalog.mysql.requiredFields.foo // [1,2,3]
conf.music.catalog.mysql.requiredFields.trackQuery[0].foo // {} <-- WTF
conf.music.catalog.mysql.requiredFields.trackQuery[0].table // "tracks"
Any idea what's going on? Yes, I can move the fields array to a higher level namespace and it will work - one step up actually. If I put it directly under requiredFields it will stay populated, but that's not an ideal solution.
I've confirmed here that it's not an ECMAScript bug and it's not my object structure, because it works as expected.
I'm running Node 0.10.3 on Ubuntu with these dependencies:
"dependencies" : {
"express" : "3.1.0",
"redis" : "0.8.2",
"jade" : "0.28.2",
"mysql" : "2.0.0-alpha7",
"mongodb" : "*",
"config" : "0.4.22"
}
I thought it might be that config module, but even when I bypass it the issue remains.
UPDATEHere is the output from: console.log(util.inspect(config.music.catalog.mysql.requiredFields.trackQuery[0], { showHidden: true, depth: null }));
-- though it doesn't really help much. I'm looking into more helpful flags, open to suggestions.
{ table: [Getter/Setter],
alias: [Getter/Setter],
foo: [Getter/Setter],
fields: [Getter/Setter],
[__watchers]:
{ table:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ],
alias:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ],
foo:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ],
fields:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ] },
[__propertyValues]:
{ table: [ 'tracks', [length]: 1 ],
alias: [ 't', [length]: 1 ],
foo: [ { [__watchers]: {}, [__propertyValues]: {} }, [length]: 1 ],
fields: [ { [__watchers]: {}, [__propertyValues]: {} }, [length]: 1 ] } }
I can reproduce the problems when the file is read using the config module, so I don't think you're bypassing it correctly.
Also, when I increase DEFAULT_CLONE_DEPTH in config/lib/config.js (it doesn't seem to be configurable from the outside, but I'm not very familiar with it), it works:
> console.log(conf.music.catalog.mysql.requiredFields.trackQuery[0].foo)
[ [Getter/Setter], [Getter/Setter], [Getter/Setter] ]

Categories

Resources