Real Bob
Real Bob

Reputation: 33

jQuery, parse single xml list into multiple unordered lists

Source XML looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<area>
    <ticket>
        <ticketnumber>001</ticketnumber>
        <location>Location</location>
    </ticket>
    <ticket>
        <ticketnumber>001</ticketnumber>
        <location>Location</location>
    </ticket>
    <ticket>
        <ticketnumber>001</ticketnumber>
        <location>Location</location>
    </ticket>...
</area>

I can parse this into an existing un-ordered list using the following code:

$(document).ready(function(){
    $.ajax({
        type: "GET",
        url: "feed.xml",
        dataType: "xml",
        success: function(xml) {
                $(xml).find('ticket').each(function(){
                    var varTicket = $(this).find('ticketnumber').text();
                    var varLocation = $(this).find('location').text();
                    var varTheHTML = '<li>'+varTicket+' '+varLocation+'</li>';
                    $(varTheHTML).appendTo("#ticket-test");
                });
        },
        error: function() {
            alert("The XML File could not be processed correctly.");
        }
    });

});

This provides me with a populated list as expected.

<ul id="ticket-test">
    <li>001 Location</li>
    <li>001 Location</li>
    <li>001 Location</li>...
</ul>

The problems begin to arise when I need to split this list into multiple lists, ideally nested in the master list. The new structure would now be:

<ul id="ticket-test">
    <li>
        <ul>
            <li>001 Location</li>
            <li>001 Location</li>
            <li>001 Location</li>...
        </ul>
    </li>
    <li>
        <ul>
            <li>001 Location</li>
            <li>001 Location</li>
            <li>001 Location</li>...
        </ul>
    </li>...
</ul>

The source XML is essentially a flat list, so I need to assign these list items into chunks of, say, 10 or so (used later with unslider).

I have tried running counters within the .each function and using a return false to jump back out again, but the code quickly becomes a spaghetti junction, I'm certain there is a more elegant way of achieving this.

I've also tried .split and for loops, but keep hitting a brick wall.

Upvotes: 3

Views: 651

Answers (4)

madalinivascu
madalinivascu

Reputation: 32354

You can do something like this

  $(document).ready(function() {
    $.ajax({
      type: "GET",
      url: "feed.xml",
      dataType: "xml",
      success: function(xml) {
        var html = '<li><ul>';
        var counter = 10;
        $(xml).find('ticket').each(function(i, v) {
          var varTicket = $(v).find('ticketnumber').text();
          var varLocation = $(v).find('location').text();
          if (i > 0 && i % counter == 0) {
            html += '</ul></li><li><ul>';
          }
          html += '<li>' + varTicket + ' ' + varLocation + '</li>';



        });
        $(html + '</ul></li>').appendTo("#ticket-test");
      },
      error: function() {
        alert("The XML File could not be processed correctly.");
      }
    });

  });

see demo:https://jsfiddle.net/y0d1or6h/

Upvotes: 1

guest271314
guest271314

Reputation: 1

You can use existing pattern at Question, then utilize .slice(), .wrapAll(), .parent(), .wrap(), recursion. Create two variables defined as 0, 10 respectively, increment variables by 10 within recursive call to function, if greatest variable is less than or equal to total #ticket-test li .length

var tickets = $("#ticket-test li");

function wrapListItems (el, num, i = 0, n = num) {
  if (n <= tickets.length) {
    el.slice(i, n).wrapAll("<ul>").parent().wrap("<li>");
    i += num;
    n += num;
    wrapListItems(el, num, i, n);
  } 
};

wrapListItems(tickets, 10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<ul id="ticket-test">
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
  <li>001 Location</li>
</ul>

Upvotes: 0

weizong song
weizong song

Reputation: 535

var counter = 2;//change to whatever u need
var mainHtmlElement = $('#ticket-test');
var htmlElement;

$('xml').find('ticket').each(function(index){
  if(index % counter == 0) {
    htmlElement = $('<ul class="level_2"></ul>');
    var el_li = $('<li class="level_1"></li>');
    htmlElement.appendTo(el_li);
    el_li.appendTo(mainHtmlElement);
  }
  var varTicket = $(this).find('ticketnumber').text();
  var varLocation = $(this).find('location').text();
  htmlElement.append('<li class="level_2">'+varTicket+' '+varLocation+'</li>');
});

Upvotes: 0

vijayP
vijayP

Reputation: 11502

Please check this approach:

$(document).ready(function() {
  var xmlString =
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
    '<area>' +
    '<ticket>' +
    '<ticketnumber>001</ticketnumber>' +
    '<location>Location</location>' +
    '</ticket>' +
    '<ticket>' +
    '<ticketnumber>002</ticketnumber>' +
    '<location>Location</location>' +
    '</ticket>' +
    '<ticket>' +
    '<ticketnumber>003</ticketnumber>' +
    '<location>Location</location>' +
    '</ticket>' +
    '<ticket>' +
    '<ticketnumber>004</ticketnumber>' +
    '<location>Location</location>' +
    '</ticket>' +
    '<ticket>' +
    '<ticketnumber>005</ticketnumber>' +
    '<location>Location</location>' +
    '</ticket>' +
    '<ticket>' +
    '<ticketnumber>006</ticketnumber>' +
    '<location>Location</location>' +
    '</ticket>' +
    '</area>';

  var xmlDoc = jQuery.parseXML(xmlString);
  var tempUL = $('<ul></ul>'); //creating a temp ul tag
  $(xmlDoc).find('ticket').each(function() {
    var varTicket = $(this).find('ticketnumber').text();
    var varLocation = $(this).find('location').text();
    var varTheHTML = '<li>' + varTicket + ' ' + varLocation + '</li>';
    tempUL.append(varTheHTML)

  });
  
  //change below number as per your requirement
  var numberOfLi = 3;
  
  while (1) {

    var liSet = tempUL.find("li:lt(" + numberOfLi + ")").detach(); //detaching the set of li to make new ul 
    var newUL = $("<ul></ul>").append(liSet);
    var topLI = $("<li></li>").append(newUL);
    topLI.appendTo("#ticket-test");

    if (tempUL.find("li").length == 0)
      break;
  }

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
my list
<ul id="ticket-test"></ul>

Upvotes: 0

Related Questions