1

I am trying to convert a nested xml document to an unordered list using jquery.The xml document is

    <?xml version="1.0" encoding="utf-8"?>
    <Parent>
    <name>Director</name>
    <Children>Exe Director1</Children>
    <Children>Exe Director2</Children>
    <Parent>
        <name>Exe Director3</name>
        <Children>Sub Director 1</Children>
        <Children>Sub Director 2</Children>
        <Parent>
            <name>Sub Director 3</name>
            <Children>Cameraman 1</Children>
            <Children>Cameraman 2</Children>
        </Parent>
    </Parent>    
</Parent>

The expected output:

 <ul>
    <li>Director
        <ul>
            <li>Exe Director 1</li>
            <li>Exe Director 2</li>
            <li>Exe Director 3
                <ul>
                    <li>Sub Director 1</li>
                    <li>Sub Director 2</li>
                    <li>Sub Director 3
                        <ul>
                            <li>Cameraman 1</li>
                            <li>Cameraman 2</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

The output which I am getting.

 <ul>
        <li>Director</li>
        <ul>
            <li>Exe Director1</li>
            <li>Exe Director2</li>
            <li>Exe Director3</li>
            <ul>
                <li>Sub Director 1</li>
                <li>Sub Director 2</li>
                <li>Sub Director 3</li>
                <ul>
                    <li>Cameraman 1</li>
                    <li>Cameraman 2</li>
                </ul>
            </ul>
        </ul>
    </ul>

As you can see,the Children are not getting created inside the parent li but outside it The latest version of the code

    <!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    var levels;
    $(document).ready(function() 
    {
        $.ajax({
            type: "GET",
            url: "test.xml",
            dataType: "xml",
            success: function (xml) { 
                var $ul = xmlParser(xml, $('#ListContainer'));
            }
        });
    });

    function xmlParser(xml,ul) {
        $(xml).contents().each(function (i, el) 
        {
            if (el.nodeName.toUpperCase() == "CHILDREN") 
            {
               $("<li>").text($(el).text()).appendTo($('ul:last')); // Append <li> Children
            } else if (el.nodeName.toUpperCase() == "NAME") 
            {
                $('<li>').text($(el).text()).appendTo(ul);
                $('<ul>').insertAfter($("li:last"));
            }
            else if (el.nodeName.toUpperCase() == "PARENT") 
            {
               if($('ul').length == 0)
                {
                    ul = ul.append('<ul>');
                }
                ul.append(xmlParser($(el),$("ul:last") )); // Recursively append the other Parent
            }
        });
        return ul;
    }
</script>
</head>
<body>
    <div id="ListContainer"></div>
</body>
</html>

I am breaking my head over this code.Can you guys help me out with what might be going wrong!

Thanks

4
  • 1
    move $("#ListContainer").append($ul); out of recursion Commented Oct 3, 2012 at 8:44
  • @rt2800 Do I need to place a check when the xml is emptied , call a function from there and write the append code in that function Commented Oct 3, 2012 at 8:47
  • 1
    create <UL> outside xmlParser() method and pass it as parentElem. e.g. var $ul = xmlParser(xml, $('<ul>')); $("#ListContainer").append($ul) in success callback of $.ajax. Return $ul as output result of xmlParser() function Commented Oct 3, 2012 at 9:25
  • If you could post your comment as an answer,I could give the "accept"! Commented Oct 3, 2012 at 10:25

4 Answers 4

1

You are appending PARENT element to same "ul" element for all "PARENT" contents. use

 $ul.find('li').last().append(xmlParser($(el)));

instead of

 $ul.append(xmlParser($(el)));

refer below link for last api:

http://api.jquery.com/last/

Sign up to request clarification or add additional context in comments.

1 Comment

tried that.Still gives the same result.Also,how can I move $("#ListContainer").append($ul); out of recursion
1

My suggestion is to use jQuery's map function recursively, as in the following example:

<script type="text/javascript">
$(function() {
    var map = function() {
            if ($(this).is("parent")) {
                var children = $(this).children().map(map).get().join('');
                $(this).children().remove();
                var result = "<li>" + $(this).text();
                return result + "<ul>" + children + "</ul></li>";
            }

            if ($(this).is("Children")) {
                return "<li>" + $(this).text() + "</li>";
            }
        };

    $.get("test.xml", function(data) {
        var result = $(data).map(map);
        $("div").html("<ul>" + result[0] + "</ul>");
    }, "html");
}); 
</script>

This ensures that the input tree is traversed completely, and that the resulting output has the same "indentations" as the input.

Notice that map() returns an array, so the resulting string is present as the first item of the array.

3 Comments

This removes the parent names from the list and prints only the child nodes? Please take a look at the xml code,the expected output and the generated output.
Apologies. I amended the code, which should create the desired structure now.
The list is generated just fine,the only issue being that the parent's name is not coming inside the list!
1

Here is Consolidation of my comments into a coherent answer-->

  1. move $("#ListContainer").append($ul); out of recursion;
  2. create <UL> outside xmlParser() method and pass it as parentElem. e.g. var $ul = xmlParser(xml, $('<ul>')); $("#ListContainer").append($ul) (in success callback of $.ajax)
  3. Return $ul as output result of xmlParser() function

1 Comment

Thanks for your help rt2800. Unfortunately , SO doesn't allow a user to accept more than one answer.Thanks again!
0

You are appending PARENT element to same "ul" element for all "PARENT" contents. use

$ul.find('li').last().append(xmlParser($(el)));

instead of

$ul.append(xmlParser($(el)));

Comments

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.