【问题标题】:jQuery parse xml into nested listjQuery 将 xml 解析为嵌套列表
【发布时间】:2016-03-15 14:56:00
【问题描述】:

我有一些来自 web 服务的 xml,我想解析并创建一个嵌套的无序列表,以便我可以使用 CSS 设置样式以使其看起来像树视图。 xml如下:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfNavMenuItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
    <NavMenuItem>
        <DOMAIN_USERNAME>SomeUser</DOMAIN_USERNAME>
        <PRIMARY_FOLDER>XYZ HR EMP SELF SERVICE</PRIMARY_FOLDER>
        <MENU_DISPLAY_NAME>Accommodation Request</MENU_DISPLAY_NAME>
    </NavMenuItem>
    <NavMenuItem>
        <DOMAIN_USERNAME>SomeUser</DOMAIN_USERNAME>
        <PRIMARY_FOLDER>XYZ HR EMP SELF SERVICE</PRIMARY_FOLDER>
        <MENU_DISPLAY_NAME>Additional Personal Information</MENU_DISPLAY_NAME>
    </NavMenuItem>
    <NavMenuItem>
        <DOMAIN_USERNAME>SomeUser</DOMAIN_USERNAME>
        <PRIMARY_FOLDER>XYZ HR EMP SELF SERVICE</PRIMARY_FOLDER>
        <MENU_DISPLAY_NAME>All Actions Awaiting Your Attention</MENU_DISPLAY_NAME>
    </NavMenuItem>
    <NavMenuItem>
        <DOMAIN_USERNAME>SomeUser</DOMAIN_USERNAME>
        <PRIMARY_FOLDER>XYZ CORP HR TIME SELF SERVICE</PRIMARY_FOLDER>
        <SECONDARY_FOLDER>Time</SECONDARY_FOLDER>
        <MENU_DISPLAY_NAME>Create Timecard</MENU_DISPLAY_NAME>
    </NavMenuItem>
    <NavMenuItem>
        <DOMAIN_USERNAME>SomeUser</DOMAIN_USERNAME>
        <PRIMARY_FOLDER>XYZ CORP HR TIME SELF SERVICE</PRIMARY_FOLDER>
        <SECONDARY_FOLDER>Time</SECONDARY_FOLDER>
        <MENU_DISPLAY_NAME>Recent Timecards</MENU_DISPLAY_NAME>
    </NavMenuItem>
    <NavMenuItem>
        <DOMAIN_USERNAME>SomeUser</DOMAIN_USERNAME>
        <PRIMARY_FOLDER>XYZ CORP HR TIME SELF SERVICE</PRIMARY_FOLDER>
        <SECONDARY_FOLDER>Time</SECONDARY_FOLDER>
        <MENU_DISPLAY_NAME>Timecard Search</MENU_DISPLAY_NAME>
    </NavMenuItem>
</ArrayOfNavMenuItem>

到目前为止,我可怜的人对 jQuery 的尝试。在遍历每个导航项并将它们添加到适当文件夹内的&lt;li&gt;&lt;/li&gt; 之前,我不确定如何捕获主文件夹、辅助文件夹结构

My fiddle is here..

//AJAX CALL
$(response).find('NavMenuItem').each(function (index) {
var test = ($(this).find('SECONDARY_FOLDER').length > 0) ? '<ul><li><label for="subfolder' + index +'">' + $(this).find("SECONDARY_FOLDER").text() + '</label><input type="checkbox" id="subfolder' + index + '">' : '';            
$('.SearchResults').append('<ul class="tree"><li><label for="folder' + index + '">' + $(this).find("PRIMARY_FOLDER").text() + '</label>'
  + '<input type="checkbox" checked id="folder' + index + '" />'
  + test
  + '<ul><li class="file"><a href="#">' + $(this).find("MENU_DISPLAY_NAME").text() + '</a></li></ul>'       
  + '</li></ul>');             
});

但我想要的 HTML 输出是这样的:

    <ul class="tree">
        <li>
          <label for="folder1">XYZ CORP HR TIME SELF SERVICE </label> 
          <input type="checkbox" checked id="folder1" />   
            <ul>
                <li><label for="subfolder1">Time</label> <input type="checkbox" id="subfolder1" />

                        <ul>
                            <li class="file"><a href="#" target="_tab">Create Timecard</a></li>
                            <li class="file"><a href="#" target="_tab">Recent Timecards</a></li>
                            <li class="file"><a href="#" target="_tab">Timecard Search</a></li>                                   
                        </ul>
                </li>
            </ul>        
        </li>

        <li>
            <label for="folder2">XYZ HR EMP SELF SERVICE</label> <input type="checkbox"  id="folder2" />                
            <ul>
                <li class="file"><a href="#" target="_tab">Accommodation Request</a></li>
                <li class="file"><a href="#" target="_tab">Additional Personal Information</a></li>
                <li class="file"><a href="#" target="_tab">All Actions Awaiting Your Attention</a></li>           
            </ul>
        </li>
    </ul>

【问题讨论】:

  • 我的问题是,我最初是通过使用 XSLT 转换 xml 来构建这个解决方案的,所以我有一种方法来模板化并在匹配时返回调用,从而有效地基于匹配创建分组。我很难在 jQuery 中模拟那种模板匹配的行为。但现在我不能使用 XSLT。它必须是客户端的所有 jQuery/JavaScript/CSS 解决方案
  • 我会为它写代码,但你检查过吗:stackoverflow.com/questions/6578154/…

标签: javascript jquery html xml html-lists


【解决方案1】:

看看这个:

var tree=$('<ul></ul>').addClass('tree'); // create an unordered list with the class 'tree'
$('NavMenuItem',response).each(function() { //for each item in NavMenuItem
    var primary=$('PRIMARY_FOLDER',this).text(); //get the text of the PRIMARY_FOLDER element
    var secondary=$('SECONDARY_FOLDER',this).text();
    var displayName=$('MENU_DISPLAY_NAME',this).text();
    if (!primary) return; // this shouldn't happen, but still, if no primary folder, ignore it
    //search for a direct listitem that has a direct child a label
    // that has the primary text as content (get the label, then return its parent)
    var li=$('>li>label:contains("'+primary+'"):first',tree).parent();
    if (!li.length) { // if not found, create it
        var index=$('>li',tree).length+1; // the number of list items in the tree plus 1
        var li=$('<li></li>') // create a list item
            .append($('<label for="folder'+index+'"></label>').text(primary)) //that contains a label
            .append('<input type="checkbox" checked id="folder'+index+'" />') // and an input
            .append('<ul></ul>'); // and an unordered list
        tree.append(li); //add it to the tree
    }
    if (secondary) { //if we have a secondary folder
        var ul = $('>ul',li); // find the unordered list in it
        // same as with primary, only here
        var li2=$('>li>label:contains("'+secondary+'"):first',ul).parent();
        if (!li2.length) {
            var index=$('>li',ul).length+1;
            var li2=$('<li></li>')
                .append($('<label for="subfolder'+index+'"></label>').text(secondary))
                .append('<input type="checkbox" checked id="subfolder'+index+'" />')
                .append('<ul></ul>')
            ul.append(li2);
        }
        li=li2; //set the current listitem to be the secondary
    }
    var ul = $('>ul',li); //get the unordered list child of the current listitem
    var index=$('>li',ul).length+1; //compute file index (if you need it)
    //add the file
    ul.append($('<li></li>').addClass('file').append($('<a href="#" target="_tab"></a>').text(displayName)));
});
// add the tree to the element with class 'SearchResults'
$('.SearchResults').append(tree);

我尽可能使用 jQuery,尽管我的意见是您应该创建一个将所有内容分组的 javascript 结构,然后将其转换为 jQuery DOM 操作。

【讨论】:

  • 哇!这正是我所需要的。这对我来说是高级的东西,所以目前正在研究你的代码。非常感谢!
  • 我用 cmets 更新了代码。我再次强调,这不是完美或高性能的代码,它只是用于学习目的。最好的代码会在数据结构中重复相同的算法,然后愚蠢地创建树。还有一些奇怪的文件夹名称可能会弄乱 :contains 选择器。此代码的优点是,您只需在 NavItem 上运行该函数即可将项目添加到页面中的现有树中
【解决方案2】:

看来您的问题是您想将无序列表添加到具有类 SearchResults 的元素中,然后将列表项添加到 XML 的每个元素的列表中,而不是为每个元素添加一个无序列表.第一步是解决这个问题:

var tree=$('<ul class="tree"></ul>').appendTo('.SearchResults');
$(response).find('NavMenuItem').each(function (index) {
    var test = ($(this).find('SECONDARY_FOLDER').length > 0) 
        ? '<ul><li><label for="subfolder' + index + '">' + $(this).find("SECONDARY_FOLDER").text() + '</label><input type="checkbox" id="subfolder' + index + '">' 
        : '';
    tree.append('<li><label for="folder' + index + '">' + $(this).find("PRIMARY_FOLDER").text() + '</label>'
         + '<input type="checkbox" checked id="folder' + index + '" />'
         + test
         + '<ul><li class="file"><a href="#">' + $(this).find("MENU_DISPLAY_NAME").text() + '</a></li></ul>'
         + '</li>');
});

然后是一些观察:

  • $(this).find('SECONDARY_FOLDER')$('SECONDARY_FOLDER',this)
  • if (X&gt;0)if (X) 相同
  • JQuery 有一种很好的链接方法的方式,因此您可以将项目附加为 您正在添加它们,例如$('<li></li').append($('<input />').css({display:'none'}).val(someValue)) 等,这可能会使 您的代码更具可读性,因此更易于维护。

希望这会有所帮助。

【讨论】:

  • 我不只是将 XML 中的每个元素添加到 SearchResults div,我还需要根据主文件夹值和辅助文件夹值对元素进行分组。如果您查看所需的 html 输出,您会明白我在说什么..
猜你喜欢
  • 2011-12-24
  • 2020-02-12
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
  • 2013-11-12
  • 1970-01-01
相关资源
最近更新 更多