patternjavascriptMinor
Optimize Recursive Function to traverse nested DOM nodes
Viewed 0 times
nodesfunctiontraversenestedrecursivedomoptimize
Problem
I wrote a recursive function that traverses nested DOM nodes of the following form:
The recursive function is the following:
so if I call that function this way:
it returns a JSON array of the following form:
However, I think that my function is way too complex, and I know that there must a better way to get the same results.
Any help will be greatly appreciated!
The recursive function is the following:
function getNestedNodes(node) {
var ary = [];
for(var i = 0; i < node.length; ++i) {
var myJSONChildren = {};
if(node[i].childElementCount) {
var myNode = node[i].children;
for(var j = 0; j < myNode.length; ++j) {
for(var k =0, attrs = myNode[j].attributes, l = attrs.length; k < l; ++k) {
myJSONChildren['tag'] = myNode[j].nodeName;
myJSONChildren[attrs.item(k).nodeName] = attrs.item(k).nodeValue;
};
}
myJSONChildren['children'] = getNestedNodes(myNode); //Recursive Call
ary.push(myJSONChildren);
};
}
return ary;
}so if I call that function this way:
var links = document.querySelectorAll('a');
getNestedNodes(node);it returns a JSON array of the following form:
[{
tag:'a',
href:"#,
title:"test",
children:[{
tag:"div",
id:"nested-image",
children:[{
tag:"img",
src:"image.jpg"
}]
}]
}]
}]However, I think that my function is way too complex, and I know that there must a better way to get the same results.
Any help will be greatly appreciated!
Solution
Note that when you do
If you ensure that you are passing the function a single node, then it can indeed be simplified a lot:
(JSfiddle here)
document.querySelectorAll you are getting not a single node but a list of nodes. This seems to be causing confusion because your function refers to node.length - but a single node does not have any length property. Your original function also does not seem to behave exactly as you want it to in that it excludes the parent node (a in your example).If you ensure that you are passing the function a single node, then it can indeed be simplified a lot:
function getTree(node) {
var r = {tag: node.nodeName}, a, i;
if (node.childElementCount) {
r.children = [];
for (i = 0; a = node.children[i]; i++) {
r.children.push(getTree(a));
}
}
for (i = 0; a = node.attributes[i]; i++) {
r[a.nodeName] = a.nodeValue;
}
return r;
}
var links = document.querySelectorAll('a');
console.log(getTree(links[0])); // only pass the first node to the function(JSfiddle here)
Code Snippets
function getTree(node) {
var r = {tag: node.nodeName}, a, i;
if (node.childElementCount) {
r.children = [];
for (i = 0; a = node.children[i]; i++) {
r.children.push(getTree(a));
}
}
for (i = 0; a = node.attributes[i]; i++) {
r[a.nodeName] = a.nodeValue;
}
return r;
}
var links = document.querySelectorAll('a');
console.log(getTree(links[0])); // only pass the first node to the functionContext
StackExchange Code Review Q#27898, answer score: 4
Revisions (0)
No revisions yet.