0

I have my XML like this:

<MenuRoot>
<menu0>Home</menu0>
<menu0 submenu="true"><name>About</name>
    <menu1>History</menu1>
    <menu1 submenu="true"><name>Within 40 years..</name>
        <menu2 submenu="true"><name>Where we are today</name>
            <menu3 submenu="true"><name>Vision of tomorrow</name>
                <menu4>Vision and Mission</menu4>
            </menu3>
        </menu2>
        <menu2>Gallery</menu2>
        <menu2>Contact Us</menu2>
    </menu1>
</menu0>
<menu0>About</menu0>
</MenuRoot>

And I am using this recursion code to load it:

$(document).ready(function()
 {
     $.ajax({
         type: "GET",
         url: "/static/menu_.xml",
         dataType: "xml",
         success: function(xml) {
         html = nodeMarkup(xml.documentElement);
         document.getElementById('menulist').innerHTML = html;}
         })
 });

function nodeMarkup( node ){
    if( node.childNodes.length ) {
        var list = '', header = '';
        for( var index = 0; index < node.childNodes.length; index++ ) {
            if( node.childNodes[index].tagName == 'name' ) {
                header = node.childNodes[index].textContent;
            } else {
                list += nodeMarkup( node.childNodes[index] );
            };
        };
        return node.hasAttribute('submenu')
            ? '<li>' + header + '<ul>' + list + '</ul></li>'
            : list;
    } else {
        return '<li>' + node.textContent + '</li>';
    };
};

I got this recursion code in here and modified the part where it loads the XML. However, I got different results when I load the XML through ajax. the output is this:

<ul id="menulist"><li>
</li><li>Home<ul></ul></li><li>
</li><li>About<ul><li>
    </li><li>History</li><li>
    </li><li>Within 40 years..<ul><li>
        </li><li>Where we are today<ul><li>
            </li><li>Vision of tomorrow<ul><li>
                </li><li>Vision and Mission</li><li>
            </li></ul></li><li>
        </li></ul></li><li>
        </li><li>Gallery</li><li>
        </li><li>Contact Us</li><li>
    </li></ul></li><li>
</li></ul></li><li>
</li><li>About</li><li>
</li></ul>

But when I manually add the XML through a variable, it loads correctly like this, just how I want:

<ul id="menulist">
  <li>Home</li>
  <li>About
    <ul>
      <li>History</li>
      <li>Within 40 years..
        <ul>
          <li>Where we are today
            <ul>
              <li>Vision of tomorrow
                <ul>
                  <li>Vision and Mission</li>
                </ul>
              </li>
            </ul>
          </li>
          <li>Gallery</li>
          <li>Contact Us</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>About</li>
</ul>

Can anybody help me with this? Thank you in advance and I will appreciate any suggestions and comments

Community
  • 1
  • 1
predator
  • 477
  • 2
  • 6
  • 22
  • Could it be that your code is picking up text nodes created by whitespace in the xml? – BAM5 Dec 07 '15 at 03:02
  • I am not sure myself.. @BAM5 lemme check – predator Dec 07 '15 at 03:09
  • @BAM5 i added whitespaces in the manual example and indeed, it is picking up whitespaces.. How can I avoid that? – predator Dec 07 '15 at 03:11
  • Jas's answer should solve your problems. Use `.children`, which refers to any sub element, instead of `.childNodes`, which refers to any node. Any characters in your markup will create a text node, and thus you want to ignore them. – BAM5 Dec 07 '15 at 03:42

1 Answers1

0

Looking at the code for your function, appears you are using node.childNodes.length, which is 7 and using the index on that. Make use of node.children.length which is 3.

function nodeMarkupOne( node ) {

    if ( node.children.length ) {
            var list = '', header = '';
            for ( var index = 0; index < node.children.length; index++ ) {
                    if ( node.children[index].tagName == 'name' ) {
                            header = node.children[index].textContent;
                    } else {
                            list += nodeMarkupOne(node.children[index]);
                    }
            }
            console.log(list);
            return node.hasAttribute('submenu') ? '<li>' + header + '<ul>' + list + '</ul></li>' : list;
    }  else {
            return '<li>' + node.textContent + '</li>';
    }
};
Richard Erickson
  • 2,568
  • 8
  • 26
  • 39
Jas
  • 336
  • 2
  • 7
  • You may want to refer the difference between ".childNodes" vs ".children" http://stackoverflow.com/questions/7935689/what-is-the-difference-between-children-and-childnodes-in-javascript – Jas Dec 07 '15 at 03:26
  • Great! It worked well! This is a follow up question, what if I added an attribute per element tag? How will I retrieve it and call it? For example: `` – predator Dec 07 '15 at 06:46
  • To get the attribute value from the menu item, you use node.getAttribute('url').. modify the code below.. if ( node.hasAttribute('url') ) { return '
  • ' + node.textContent + '
  • ' } return '
  • ' + node.textContent + '
  • '; – Jas Dec 07 '15 at 13:06
  • That did it! Thank you for helping me out! – predator Dec 08 '15 at 01:58