Reputation: 721
I have an XML data, which I need to convert into an array, XML data has a hierarchy but it is on the same level hence the problem to identify. I've given an expected output array below along with my work.
This following XML data can have multiple hierarchies
<data>
<GROUP NAME="Sundry Debtors">
<PARENT></PARENT>
</GROUP>
<GROUP NAME="Sundry Debtors-Pune">
<PARENT>Sundry Debtors</PARENT>
</GROUP>
<GROUP NAME="Sundry Debtors-Akurdi">
<PARENT>Sundry Debtors-Pune</PARENT>
</GROUP>
<GROUP NAME="Sundry Creditors">
<PARENT></PARENT>
</GROUP>
<GROUP NAME="Sundry Creditors-Pune">
<PARENT>Sundry Creditors</PARENT>
</GROUP>
</data>
Following is expected output from the above xml data
let arr = [
{
name: "Sundry Debtors",
data: [{ name: "Sundry Debtors-Pune", data: [{ name: "Sundry Debtors-Akurdi", data: [] }] }]
},
{ name: "Sundry Creditors", data: [{ name: "Sundry Creditors-Pune", data: [] }] }
];
Following is what I've tried so far
<!DOCTYPE html>
<html>
<title>test</title>
<script>
//Desired output
let arr = [
{
name: "Sundry Debtors",
data: [{ name: "Sundry Debtors-Pune", data: [{ name: "Sundry Debtors-Akurdi", data: [] }] }]
},
{ name: "Sundry Creditors", data: [{ name: "Sundry Creditors-Pune", data: [] }] }
];
let text =
'<data><GROUP NAME="Sundry Debtors"><PARENT></PARENT></GROUP><GROUP NAME="Sundry Debtors-Pune"><PARENT>Sundry Debtors</PARENT></GROUP><GROUP NAME="Sundry Debtors-Akurdi"><PARENT>Sundry Debtors-Pune</PARENT></GROUP><GROUP NAME="Sundry Creditors"><PARENT></PARENT></GROUP><GROUP NAME="Sundry Creditors-Pune"><PARENT>Sundry Creditors</PARENT></GROUP></data>';
let parser = new DOMParser();
let xml = parser.parseFromString(text, "text/xml");
var node = xml.getElementsByTagName("GROUP");
let total = 0;
let levels = [];
let level = 0;
let hirarchy = [];
total = node.length;
function getChilds(parent) {
let arr = [];
for (let j = 0; j < total; j++) {
let e = node[j];
let grpName = e.getAttribute("NAME");
let parentCount = e.getElementsByTagName("PARENT")[0].childNodes.length;
if (parentCount > 0) {
let parentName = e.getElementsByTagName("PARENT")[0].childNodes[0].nodeValue;
if (parentName === parent) {
arr.push(grpName);
}
}
}
return arr;
}
function getParent(child) {
let arr = [];
for (let k = 0; k < total; k++) {
let e = node[k];
let grpName = e.getAttribute("NAME");
if (grpName === child) {
let parentCount = e.getElementsByTagName("PARENT")[0].childNodes.length;
let parentName = parentCount > 0 ? e.getElementsByTagName("PARENT")[0].childNodes[0].nodeValue : undefined;
return parentName;
}
}
}
function findNode(array, nodename) {
for (let j = 0; j < array.length; j++) {
const e = array[j];
if (e.name === nodename) {
return e;
} else {
if (e.data.length > 0) {
//console.log(e.data, nodename);
return findNode(e.data, nodename);
} else {
return null;
}
}
}
}
let new_h = [];
for (i = 0; i < total; i++) {
let e = node[i];
let grpName = e.getAttribute("NAME");
let childs = getChilds(grpName);
let parent = getParent(grpName);
//console.log(i, grpName, " --->", childs, parent);
if (!parent) {
let arr = { name: grpName, data: [] };
new_h.push(arr);
} else {
let arr = findNode(new_h, parent);
if (arr) {
arr.data.push({ name: grpName, data: [] });
} else {
}
}
}
console.log(new_h);
</script>
</html>
Upvotes: 1
Views: 77
Reputation: 26
Try following code.
<!DOCTYPE html>
<html>
<title>test</title>
<script>
let expected_output_array = [
{
name: "Sundry Debtors",
data: [{ name: "Sundry Debtors-Pune", data: [{ name: "Sundry Debtors-Akurdi", data: [] }] }]
},
{ name: "Sundry Creditors", data: [{ name: "Sundry Creditors-Pune", data: [] }] }
];
let text =
'<data><GROUP NAME="Sundry Debtors"><PARENT></PARENT></GROUP><GROUP NAME="Sundry Debtors-Pune"><PARENT>Sundry Debtors</PARENT></GROUP><GROUP NAME="Sundry Debtors-Akurdi"><PARENT>Sundry Debtors-Pune</PARENT></GROUP><GROUP NAME="Sundry Creditors"><PARENT></PARENT></GROUP><GROUP NAME="Sundry Creditors-Pune"><PARENT>Sundry Creditors</PARENT></GROUP></data>';
let parser = new DOMParser();
let xml = parser.parseFromString(text, "text/xml");
var node = xml.getElementsByTagName("GROUP");
let total = 0;
total = node.length;
function getChilds(parent) {
let arr = [];
for (let j = 0; j < total; j++) {
let e = node[j];
let grpName = e.getAttribute("NAME");
let parentCount = e.getElementsByTagName("PARENT")[0].childNodes.length;
if (parentCount > 0) {
let parentName = e.getElementsByTagName("PARENT")[0].childNodes[0].nodeValue;
if (parentName === parent) {
arr.push(grpName);
}
}
}
return arr;
}
function getParent(child) {
let arr = [];
let total = node.length;
for (let k = 0; k < total; k++) {
let e = node[k];
let grpName = e.getAttribute("NAME");
if (grpName === child) {
let parentCount = e.getElementsByTagName("PARENT")[0].childNodes.length;
let parentName = parentCount > 0 ? e.getElementsByTagName("PARENT")[0].childNodes[0].nodeValue : undefined;
return parentName;
}
}
}
function findNodeSequential(array, nodename) {
for (let k = 0; k < array.length; k++) {
const e = array[k];
if (e.name === nodename) {
return e;
} else {
if (e.data.length > 0) {
return findNodeSequential(e.data, nodename);
} else {
return null;
}
}
}
}
function findNode(array, nodename) {
for (let j = 0; j < array.length; j++) {
let e = array[j];
if (e.name === nodename) {
return e;
} else {
if (e.data.length > 0) {
e = findNodeSequential(e.data, nodename);
if (e !== null) {
return e;
}
}
}
}
}
let h = [];
for (let i = 0; i < total; i++) {
let e = node[i];
let grpName = e.getAttribute("NAME");
let childs = getChilds(grpName);
let parent = getParent(grpName);
if (!parent) {
let arr = { name: grpName, data: [] };
h.push(arr);
}
}
for (let l = 0; l < total; l++) {
let e = node[l];
let grpName = e.getAttribute("NAME");
let childs = getChilds(grpName);
let parent = getParent(grpName);
if (parent) {
let arr = findNode(h, parent);
if (arr) {
arr.data.push({ name: grpName, data: [] });
} else {
}
}
}
console.log("Expected output:", expected_output_array);
console.log("Output: ", h);
</script>
</html>
Upvotes: 1
Reputation: 11
I hope this helps,
var convert = require('xml-js');
let xmlString = `<?xml version="1.0" encoding="UTF-8"?>
<data>
<GROUP NAME="Sundry Debtors">
<PARENT></PARENT>
</GROUP>
<GROUP NAME="Sundry Debtors-Pune">
<PARENT>Sundry Debtors</PARENT>
</GROUP>
<GROUP NAME="Sundry Debtors-Akurdi">
<PARENT>Sundry Debtors-Pune</PARENT>
</GROUP>
<GROUP NAME="Sundry Creditors">
<PARENT></PARENT>
</GROUP>
<GROUP NAME="Sundry Creditors-Pune">
<PARENT>Sundry Creditors</PARENT>
</GROUP>
</data>`;
/* convert xml to json object */
result = convert.xml2js(xmlString, {compact: true, spaces: 4});
let exists_arr = [];
var group = result.data.GROUP;
function fchild(par) {
let final = [];
for (var i = 0; i <= group.length - 1; i++) {
let {_attributes, PARENT} = group[i];
/* checking if its the top-most level group (Object.keys(PARENT).length == 0 then its top level group) and does not exist in exists_arr */
if( Object.keys(PARENT).length == 0 && par == false && !exists_arr.includes(_attributes.NAME)){
/* push to exists_arr */
exists_arr.push(_attributes.NAME);
/* push to final array, also calling the function in recurtion to find the children of the current */
final.push({ name:_attributes.NAME, data:fchild(_attributes.NAME)});
}
else if(par == PARENT._text && !exists_arr.includes(_attributes.NAME) ){
/* entering if 'par' value matches with parent text & does not exist in exists_arr */
/* push to exists_arr */
exists_arr.push(_attributes.NAME);
/* push to final array, also calling the function in recurtion */
final.push({ name:_attributes.NAME, data:fchild(_attributes.NAME)});
}
}
return final;
}
console.log(JSON.stringify(fchild(false)));
Upvotes: 1