node.js transform xml into json with xml2js - javascript

I am using the node.js package xml2js to transform xml into json.
Documentation is here: https://www.npmjs.com/package/xml2js
My problem is that attributes for those xml are not correctly transformed.
example XML with multiple events
<events><event id="E0-001-098932239-8"></event><event id="E0-001-105389601-2"></event><event id="E0-001-104342965-3"></event><event id="E0-001-104830349-3"></event><event id="E0-001-105374979-6"></event><event id="E0-001-105389620-7"></event><event id="E0-001-104247759-2"></event><event id="E0-001-104342949-5">
Result from JSON.stringify(result.search.events)
The event tag is only once in the generated JSON - My expectation is that it should have multiple tags event. So I assume the transformation process went wrong. I tried multiple options for the parser like ignoreAttrs, explicitArray or explicitChildren but without success.
[{
"event": [{
"$": {
"id": "E0-001-098932239-8"
},
]
}, {
"$": {
"id": "E0-001-105389601-2"
},
}, {
"$": {
"id": "E0-001-104342965-3"
},
}, {
"$": {
"id": "E0-001-104830349-3"
},
access JSON elements
After correct transformation I expect to simply access the JSON elements via event[1].$.id
but all tries are unsuccessful:
events.event --> undefined
events.event.$ --> undefined
events.$ --> undefined
My Question is now: how can i correctly transform the xml into JSON and access the elements correctly?

Javascript is starting from 0, you should get events[0].event[0].$.id
Also, you can try with another package (camaro) with simply and easily change the desired result.
Example:
const xml = '<events><event id="E0-001-098932239-8"></event><event id="E0-001-105389601-2"></event><event id="E0-001-104342965-3"></event><event id="E0-001-104830349-3"></event><event id="E0-001-105374979-6"></event><event id="E0-001-105389620-7"></event><event id="E0-001-104247759-2"></event><event id="E0-001-104342949-5"></event></events>'
const temp = {
events: ['/events/event', {
id: '#id'
}]
}
const transform = require('camaro')
const results = transform(xml, temp)
console.log(JSON.stringify(results, null, 2))
Results
{
"events": [
{
"id": "E0-001-098932239-8"
},
{
"id": "E0-001-105389601-2"
},
{
"id": "E0-001-104342965-3"
},
{
"id": "E0-001-104830349-3"
},
{
"id": "E0-001-105374979-6"
},
{
"id": "E0-001-105389620-7"
},
{
"id": "E0-001-104247759-2"
},
{
"id": "E0-001-104342949-5"
}
]
}

Related

How to replace a JSON object value {} in Nodejs

I have the following JSON object data stored in a JSON file, which will be passed as a when performing an API call.
I want to replace "it-goes-here" with below {} block.
replaced-data:
{
"parenturl":"xxx.com",
"username":"userId",
"password":"xxx!",
"id":"id",
"url":"xxx.com",
"xxx":"xxx"
}
test.json
{
"details": it-goes-here,
"dbs": [
{
"schemas": [
{
"schemaName": "schemaName",
"tables": [
{
"tableName": "tableName",
"type": "table",
"columns": [
{
"name": "name",
"gender": "F",
"canDonate": true,
"database": "database"
},
etc.,
]
}
]
}
],
}
I have tried the code below, but it keeps giving me SyntaxError: Unexpected token
in JSON at position 28. I'm new to nodeJS, what am I doing here? What else can I try?
let data = await fs.readFileSync('./test/test.json', 'utf8').toString();
data = await JSON.parse(JSON.stringify(data).replace('it-goes-here', 'replaced-data'));
Try read and parse the test.json to JSON Object and run data.details = replacedData to replace the details object to replacedData object.

Javascript parse array of object strings into object of objects?

I am working with a 3rd party app that requires a specific structure of data for filtering a result set. I am struggling with figuring out how to parse this out as the end result isn't a conventional array of objects.
There is a function that takes in a list of IDs from an array and turns them into object strings:
Function:
// Input for articles is an array of IDs
// articles = ['kA10W000001UK2KSAW', 'kA1d0000000DB1CCAW', 'kA1d0000000DAsOCAW']
function createExclusion(articles){
let results = [];
articles.forEach(element => {
results.push(`"EqualsTo": {"Key": "sf_KnowledgeArticleId","Value": {"StringValue":"${element}"}}`)
})
return result;
}
Input Data:
let data = [
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA10W000001UK2KSAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DB1CCAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DAsOCAW"}}'
]
Desired End Result:
{
IndexId: 1,
PageSize: 2,
PageNumber: 3,
RequestedDocumentAttributes: ["_source_uri", "sf_ArticleNumber", "sf_KnowledgeArticleId"],
AttributeFilter: {
"NotFilter": {
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA10W000001UK2KSAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DB1CCAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DAsOCAW"
}
},
},
SortingConfiguration: {
"DocumentAttributeKey": "_document_title",
"SortOrder": "ASC"
}
};
}
I am trying to re-create the AttributeFilter data in the end result by taking the array of strings and parsing it into the correct form.
Example:
I was trying to get it to work with JSON.parse(), but the data isn't in the correct format for that.
Between either adjusting the createExclusion function or easily parsing it in its existing form, how can I go about turning the list of object strings into just objects as seen in the desired end result?
function parse(data) {
return {
IndexId: 1,
PageSize: 2,
PageNumber: 3,
RequestedDocumentAttributes: ["_source_uri", "sf_ArticleNumber", "sf_KnowledgeArticleId"],
AttributeFilter: {
"NotFilter": ? // Parse data here
},
SortingConfiguration: {
"DocumentAttributeKey": "_document_title",
"SortOrder": "ASC"
}
};
}
First, you cannot have an object with duplicated keys in JSON:
{
"NotFilter": {
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA10W000001UK2KSAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DB1CCAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DAsOCAW"
}
}
}
}
Your NotFilter value should be an array of objects.
Parsing JSON
Your JSON should be valid, prior to calling JSON.parse. Make sure you remove any trailing commas and wrap each line in curly-braces.
let data = [
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA10W000001UK2KSAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DB1CCAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DAsOCAW"}}'
]
const parsed = data.map(item => JSON.parse(`{${item.replace(/,$/, '')}}`));
console.log(parsed);
.as-console-wrapper { top: 0; max-height: 100% !important; }

How does one filter json after type?

So, I have a json which looks a little bit like this:
{
"data": {
"user": {
"edge_followed_by": {
"count": 22,
"page_info": {
"has_next_page": true,
"end_cursor": "Base64"
},
"edges": [
{
"node": {
"id": "id",
"username": "Username",
"full_name": "played",
"profile_pic_url": "URL"
}
}
]
}
}
}
}
And I want to filter out the username. How do I do that?
You could retrieve it with a map function there
const dataSample = {
"data": {
"user": {
"edge_followed_by": {
"count": 22,
"page_info": {
"has_next_page": true,
"end_cursor": "Base64"
},
"edges": [
{
"node": {
"id": "id",
"username": "Username",
"full_name": "played",
"profile_pic_url": "URL"
}
}
]
}
}
}
}
const getUsernames = data => {
return data.data.user.edge_followed_by.edges.map(e => e.node.username)
}
console.log(getUsernames(dataSample))
:)
This can be a little tricky to understand from the question first of all.
My interpretation of this is you want to extract a username
"Filtering" also could mean you want to remove something from a collection that passes a condition (or test) of some kind.
For example: Removing all even numbers from an array
let x = [1, 2, 4, 5, 6];
let filtered = x.filter(value => value % 2 === 0);
Now, I've looked at your json, and I think the best point of targeting this is by getting the "edges" property and running it through an inbuilt function like map; that could be used to get usernames. The edges is an array as well.
data.user.edge_followed_by.edges.map(userObject => userObject.username)
That would effectively remove all usernames from the edges if your tech stack of choice was javascript.
I got this info from a post like: https://coderin90.com/blog/2019/map-js

Push Json filtered key values to nested ul with Javascript

I need help pushing the values from a filtered json, I need this generate a nested ul list, I can not modify the json format at this point, I you check the console.log you will see the values to create the list, at this point I can't figure how to complete the 'for loop' to render the html markup needed, any help will be appreciated, this is the jsfiddle http://jsfiddle.net/43jh9hzz/, and if you check the console log you will see the values.
This is the Js:
var json='';
var property_set = new Set();
function iterate(obj, stack) {
json="<ul>";
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
}
else {
// console.log(property);
property_set.add(property);
json+="<li>";
if(typeof obj[property] !== "number") {
json+="<li>"+obj[property]+"</li>";
console.log(obj[property]);
}
}
} json += "</li>";
}
}
var listEl = document.getElementById('output');
iterate(jsonObj)
And this is the json format:
var jsonObj =
{
"level_1": [
{
"level_1_name": "CiscoSingaporeEBC",
"level_2": [
{
"level_2_name": "Khoo Tech Puat",
"level_2_id": 2222,
"level_3": [
{
"name": "Boon Leong Ong",
"id": 6919
},
{
"name": "Kiat Ho",
"id": 6917
},
{
"name": "Overall Experience",
"id": 6918
}
]
}
]
},
{
"level_1_name": "CiscoLondonEBC",
"level_2": [
{
"level_2_name": "Bernard Mathews Ltd.",
"level_2_id": 2367,
"level_3": [
{
"name": "Barry Pascolutti",
"id": 7193
},
{
"name": "Kathrine Eilersten",
"id": 7194
},
{
"name": "Martin Rowley",
"id": 7189
}
]
},
{
"level_2_name": "FNHW Day 1",
"level_2_id": 5678,
"level_3": [
{
"name": "Jurgen Gosch",
"id": 7834
},
{
"name": "Overall Experience",
"id": 7835
}
]
},
{
"level_2_name": "Groupe Steria Day 1",
"level_2_id": 2789,
"level_3": [
{
"name": "Adam Philpott",
"id": 7919
},
{
"name": "Pranav Kumar",
"id": 7921
},
{
"name": "Steve Simlo",
"id": 7928
}
]
}
]
}
]
};
enter code here
I'm not sure if I am interpretting your request correctly, but I think this is what you want: http://jsfiddle.net/mooreinteractive/43jh9hzz/1/
Basically, you are calling the iterate function to run, but then that's it. The function actually needs to also return the value it generates.
I've added to the end of the function, after the for loop completes:
return json;
Do now the function returns the value it generated, but there are some other issues too. When you recursively call the iterate function again inside the iterate function, you actually want to add what it returns to the current json string housing all of your returned value.
So on that line I changed it from:
iterate(obj[property], stack + '.' + property);
to
json += iterate(obj[property], stack + '.' + property);
Now that other value will come back as well inside the main list you were creating in the first run of the function. Ok so that's pretty close, but one more small thing. I think when you added additional surrounding LI, you actually wanted to do an UL. I changed those to ULs and now I think the result is like a UL/LI list representing the text parts of the JSON object.
Again, that may not be exactly what you were after, but I think the main take away is using the function to return the value, not just generate it, then do nothing with it.

How to parse a JSON array string in JavaScript?

I have an JSON array like this
var filter_value_data = [{"Status":[{"name":"Open","id":"1"},{"name":"Pending","id":"2"},{"name":"Resolved","id":"3"},{"name":"Closed","id":"4"},{"name":"Evaluation","id":"5"}]},{"Payment Status":[{"name":"Paid","id":"10"},{"name":"UnPaid","id":"11"},{"name":"Part Paid","id":"12"}]},{"Priority":[{"name":"Low","id":"6"},{"name":"Medium","id":"7"},{"name":"High","id":"8"},{"name":"Urgent","id":"9"}]}]
I have tried filter_value_data["Status"] which is obviously wrong. How do I get the JSON elements for Status using the names like Status,Payment Status?
filter_value_data is an array (having []), so use filter_value_data[0].Status to get the first element-object with property "Status".
It is always good to format your code in order to see the hierarchy of the structures:
var filter_value_data = [
{
"Status": [
{
"name": "Open",
"id": "1"
}, {
"name": "Pending",
"id": "2"
}, ...
]
}, {
"Payment Status": [
{
"name": "Paid",
"id": "10"
}, ...
]
}, {
"Priority": [
{
"name": "Low",
"id": "6"
}, ...
]
}
];
With your current JSON you can't get the elements with the name alone.
You can get Status with filter_value_data[0]['Status'] and Payment status with filter_value_data[1]['Payment Status'].
This is because the keys are in seperate objects in the array.
In order to get them with filter_value_data['Status'] you need to change your JSON to
var filter_value_data = {
"Status":[
{"name":"Open","id":"1"},
{"name":"Pending","id":"2"},
{"name":"Resolved","id":"3"},
{"name":"Closed","id":"4"},
{"name":"Evaluation","id":"5"}
],
"Payment Status":[
{"name":"Paid","id":"10"},
{"name":"UnPaid","id":"11"},
{"name":"Part Paid","id":"12"}
],
"Priority":[
{"name":"Low","id":"6"},
{"name":"Medium","id":"7"},
{"name":"High","id":"8"},
{"name":"Urgent","id":"9"}
]
};
I wrote this on my phone so it's not as well-formatted as usual. I'll change it ASAP.
With your current JSON, created a result which might be helpful for you.
JS:
$.each(filter_value_data,function(ind,val){
var sta = val.Status; // Status Object get displayed
for(var i=0;i<sta.length;i++){
var idVal= sta[i].id;
var nameVal = sta[i].name;
Statusarray.push(idVal,nameVal);
console.log(Statusarray);
}
})
FiddleDemo
You can use below code, it will return status object
filter_value_data[0]['Status']
filter_value_data[0]['Payment Status']
to get Single value you use :
filter_value_data[0]['Status'][0]['name']

Categories