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

4
  • Could it be that your code is picking up text nodes created by whitespace in the xml? Commented Dec 7, 2015 at 3:02
  • I am not sure myself.. @BAM5 lemme check Commented Dec 7, 2015 at 3:09
  • @BAM5 i added whitespaces in the manual example and indeed, it is picking up whitespaces.. How can I avoid that? Commented Dec 7, 2015 at 3: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. Commented Dec 7, 2015 at 3:42

1 Answer 1

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>';
    }
};
Sign up to request clarification or add additional context in comments.

4 Comments

You may want to refer the difference between ".childNodes" vs ".children" stackoverflow.com/questions/7935689/…
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: <menu0 url="home">
To get the attribute value from the menu item, you use node.getAttribute('url').. modify the code below.. if ( node.hasAttribute('url') ) { return '<li><a href="' + node.getAttribute('url') + '">' + node.textContent + '</a></li>' } return '<li>' + node.textContent + '</li>';
That did it! Thank you for helping me out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.