0

I need some help with my JavaScript, i am trying to sorting XML data with the help of JavaScript, and i am successful doing the sorting part, but the output is returning [object Object], which i don't want it to be printed out, so i need some help to get this thing fixed so that i get a proper output. I am attaching a live fiddle. All these needs to be done with JavaScript and not JQUERY.

I don't want [object Object],[object Object] to be printed as output. I want the output as following format.

Live Fiddle

bookstore 
   |
   |__book 
   |    |_____title
   |    |_____author
   |    |_____year
   |    |_____price
   |
   |__book 
   |
   |__book 
   |
   |__book  

function generate(obj){
//  alert((obj[prop])+": "+typeof(obj));
    var ul = document.createElement("ul"),
        li,span;
    for (var prop in obj){
        li = document.createElement("li");
        li.appendChild(document.createTextNode(obj[prop]));
        li.onclick = function(e) {
                e = e || window.event;
                if ((e.target || e.srcElement).tagName !== "LI") return;
                var classNames = this.className;
                if (classNames.indexOf("hidden") == -1) {
                    this.className += "hidden";
                } else {
                    this.className = this.className.replace("hidden", "");
                }
                if (!e)
                    e = window.event;
                    if (e.stopPropagation) {
                      e.stopPropagation();
                    }
                else {
                    e.cancelBubble = true;
                }
            }
        if (typeof obj[prop] == "object" && Objectkeys(obj[prop]).length) {
                li.appendChild(generate(obj[prop]));
            } else {
                li.className += "leaf";
            }
            ul.appendChild(li);
            console.log(ul);
        }
        return ul;
    }   

Thank you

4 Answers4

1

Break down your problem into smaller problems;

function li(text) { // create a text list item
    var node = document.createElement('li');
    if (text) node.appendChild(document.createTextNode(text));
    return node;
}

function getTextItems(parent, tag) { // get list of text from nodes
    var list = parent.getElementsByTagName(tag),
        arr = [], i;
    for (i = 0; i < list.length; ++i) {
        arr[i] = list[i].textContent;
    }
    return arr;
}

function bookToUl(node) { // parse <book>
    var ul = document.createElement('ul'),
        title = getTextItems(node, 'title')[0],
        year = getTextItems(node, 'year')[0],
        authors = getTextItems(node, 'author'),
        price = getTextItems(node, 'price')[0];
    ul.appendChild(li(title));
    ul.appendChild(li(year));
    ul.appendChild(li(authors.join(', ')));
    ul.appendChild(li('$' + price));
    console.log(ul);
    return ul;
}

function bookstoreToUl(store) { // parse <bookstore>
    var books = store.getElementsByTagName('book'), i,
        ul = document.createElement('ul'), li;
    for (i = 0; i < books.length; ++i) {
        li = document.createElement('li');
        li.appendChild(bookToUl(books[i]));
        ul.appendChild(li);
    }
    return ul;
}

var d = new DOMParser().parseFromString(txt, 'text/xml');
document.body.appendChild(
    bookstoreToUl(
        d.getElementsByTagName('bookstore')[0]
    )
);

DEMO

Paul S.
  • 64,864
  • 9
  • 122
  • 138
0

I think your problem is that you don't understand the structure of the object.

If you do add console.log(parsedObject); at the bottom of your script, you can see the structure of the object in your console.

for example (console output):

Object
    children: Array[4]
        0: Object
            children: Array[4]
            name: "book"
            __proto__: Object
        1: Object
        2: Object
        3: Object
        length: 4 // the length of the array
        __proto__: Array[0]
name: "bookstore"
__proto__: Object

So as you can see in this structure, to output bookstore you will need to use: obj['name']

However, if you want to output the name of the children then you will need to use:

obj['children'][prop]['name'] instead of obj[prop],

So if you want to loop over the children you will need to use:

for(var prop in obj['children']){ instead of for(var prop in obj){ `

I hope this helps you a bit.

Andy
  • 2,892
  • 2
  • 26
  • 33
0

A problem is right here:

li.appendChild(document.createTextNode(obj[prop]));

You are creating a text node and assigning it obj[prop] which if it is isn't already a string, it will be converted to a string. If it's an object, the string conversion of an object is [object Object].

What you need to do is to test if obj[prop] is an object who's properties you need to iterate, an array who's items you need to iterate or just a node that you want to display.

Right now, your code doesn't seem to be organized such that the issue can be quickly fixed with a few lines of code being changed. The main approach you need to take is to call a function on the next node in the tree. At the very beginning of that function, it needs to figure out what it has. Does it have a leaf node (just display it) or does it have a parent node (must display parent and then iterate over children). Your code is attempting to just stringify the parent and display it and that gives you the dumb object conversion you're seeing. You have to make your code smarter than that to actually detect when you have a parent node and treat it accordingly.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Something like `if(typeof obj[prop] == 'object') //do somthing` – PitaJ Mar 02 '14 at 17:27
  • i am trying to figureout what code should is use to perform this test, please tell me how should is perform that check – user3314588 Mar 02 '14 at 17:27
  • @user3314588 - I'm looking into your jsFiddle. The first thing I noticed is that I'm running into an array at that line. You will have to detect the array as an array and iterate over its contents, but your code isn't structure quite right to easily iterate over it without changing some other things around. – jfriend00 Mar 02 '14 at 17:34
  • This is the same as I said on OP's earlier question [**here**](http://stackoverflow.com/a/22128899/1615483). I think OP is really asking "convert this xml to a ul-tree for me", so I have answered differently on this one... – Paul S. Mar 02 '14 at 17:59
0

Problem

I think the fundamental problem was iterating over the object properties. Since you know that each object contains a name and a children array list, you want to iterate over only the children array list. If you iterate over the object properties, you'll end up with the [object Object] because you'll be appending a property to the list.

Solution

I took a stab at this and here's what I came up with. You'll have to tailor it to your needs. I used the forEach function to iterate over each child. You could also write a loop which is faster.

function generate(list) {
    // Initialize variables
    var ul = document.createElement('ul');
    var li = document.createElement('li');

    if (typeof list !== 'undefined') {
      li = document.createElement('li');
      li.appendChild(document.createTextNode(list.name));

      // If children are defined, then for each child,
      // create its list and append it to this list item.
      if (typeof list.children !== 'undefined') {
        list.children.forEach(function(child) {
           li.appendChild(generate(child));
        });
      }
      ul.appendChild(li.cloneNode(true));
    }

    return ul;
};
Pete
  • 3,246
  • 4
  • 24
  • 43