简体   繁体   中英

nested xml into unordered list in jquery

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

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/

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.

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. eg var $ul = xmlParser(xml, $('<ul>')); $("#ListContainer").append($ul) var $ul = xmlParser(xml, $('<ul>')); $("#ListContainer").append($ul) (in success callback of $.ajax)
  3. Return $ul as output result of xmlParser() function

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)));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM