skip to Main Content

I also need to put the array in a variable.

I’m using .DataTable for pagination but it doesn’t accept tables that are created from xml using Javascript and according to this https://datatables.net/forums/discussion/2689, I need to convert my xml into 2d array.

Here’s my xml file

<person>
    <data>
        <name>juan</name>
        <city>tokyo</city>
        <age>20</age>
        <sex>m</sex>
    </data>
    <data>
        <name>pedro</name>
        <city>manila</city>
        <age>22</age>
        <sex>m</sex>
    </data>
    <data>
        <name>maria</name>
        <city>bangkok</city>
        <age>23</age>
        <sex>f</sex>
    </data>
</person>

My 2D array should look like this:

var person =[
    ["juan","tokyo","20","m"],
    ["pedro","manila","22","m"],
    ["maria","bangkok","23","f"],
];

This is my javascript code. The output shows on my html page but I cannot use it for the DataTable that is why i need to store it in an javascript array. How can I modify this code so i can put it in a variable instead of displaying it in an html page?

function readperson(){
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function(){
        if (this.readyState == 4 && this.status ==200){
            writeperson(this);
        }
    }
    xmlhttp.open("GET", "person.xml", true);
    xmlhttp.send();
}

function writeperson(xml){
    var x,i,xmlDoc,txt,ths,trs,tre,the;
    xmlDoc = xml.responseXML;
    var person =xmlDoc.getElementsByTagName("data");
    var l = person.length;
    var nodes = person[0].childNodes[0];
    //var l3 = nodes[0].length;
    var l2 = person[0].childNodes[0].nodeValue;

    var arr = [];
    //orders.length = 3 since two <data> tag
     for(i=0; i < person.length; i++){
        //will add brackets inside the array arr
        arr.push([]);//example: if arr.push("hello") output is hello,hello,hello
        
        arr[i][0]=person[i].getElementsByTagName("name")[0].childNodes[0].nodeValue
        arr[i][1]=person[i].getElementsByTagName("city")[0].childNodes[0].nodeValue
        arr[i][2]=person[i].getElementsByTagName("age")[0].childNodes[0].nodeValue
        arr[i][3]=person[i].getElementsByTagName("sex")[0].childNodes[0].nodeValue
    }
    document.getElementById("person").innerHTML = arr;
}

When I use a return statement instead of the innerHTML it does not work.

UPDATE
I figured it out. Here’s my final code

$(document).ready(function () {
  $.ajax({
    type: "GET",
    url: "person.xml",
    dataType: "xml",
    success: function (xml) {
      const res = [];
      $(xml).find("person > data").each(function (i, person) {
          res.push([
            $(this).find("name", person).text(),
            $(this).find("city", person).text(),
            $(this).find("age", person).text(),
            $(this).find("sex", person).text(),
          ]);
        });

      $("#person_table").DataTable({
        data: res,
        columns: [
          { title: "Name" },
          { title: "Address" },
          { title: "Age" },
          { title: "Sex." },
        ],
      });
    },
  });
});

3

Answers


  1. You can use jQuery (you have this tag below your question) to parse html tags. First convert XML data string to DOM HTML, then do all searching and extraction how you regularly would with jQuery:

    // XML data string
    const xml = `
    <person>
        <data>
            <name>juan</name>
            <city>tokyo</city>
            <age>20</age>
            <sex>m</sex>
        </data>
        <data>
            <name>pedro</name>
            <city>manila</city>
            <age>22</age>
            <sex>m</sex>
        </data>
        <data>
            <name>maria</name>
            <city>bangkok</city>
            <age>23</age>
            <sex>f</sex>
        </data>
    </person>
    `;
    
    // Convert to DOM HTML
    const html = $.parseHTML(xml);
    
    // Set array for result
    const res = [];
    
    // Parse html, find data tags,
    // loop through it's content
    $(html).find("data").each(function() {
      // For each data element push
      // required data to array
      res.push([
        $(this).find("name").text(),
        $(this).find("city").text(),
        $(this).find("age").text(),
        $(this).find("sex").text()
      ]);
    });
    
    // Test
    console.log(res);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    Login or Signup to reply.
  2. Consider the following.

    Example: https://jsfiddle.net/Twisty/1vw3z6mf/

    JavaScript

    $(function() {
      function xmlToArray(xml) {
        var arr = [];
        $(xml).find("person > data").each(function(i, person) {
          arr.push([
            $("name", person).text(),
            $("city", person).text(),
            $("age", person).text(),
            $("sex", person).text()
          ]);
        });
        console.log("Converted", arr);
        return arr;
      }
    
      function writeperson(xml) {
        console.log("Write People");
        var people = xmlToArray(xml);
        $("#person").html(people);
      }
    
      function readperson() {
        console.log("Read People");
        $.get("person.xml", function(data) {
          writeperson(data);
        });
      }
    
      $("button").click(readperson);
    });
    

    jQuery can read XML just like it can reach HTML. So you can use jQuery selectors to traverse the XML. You can do this with .find() or with $("elem", object) shorthand which is the same.

    The logic iterates over each data portion and creates Arrays at each index. This gives you an Array of Arrays or a 2D Array that Datatables can use.

    I cleaned up other code elements to all use jQuery, yet there is nothing wrong with using JavaScript if you choose.

    Login or Signup to reply.
  3. Here is another Vanilla JS take on it with fetch() and DOMParser():

    /* uncomment the next line for real application: */
    // fetch("person.xml").then(r=>r.text()).then(txt=>{
      const atts="name,city,age,sex".split(",");
    /* XML data string for SO demo, remove line for real application: */
      const txt = `<person><data><name>juan</name><city>tokyo</city><age>20</age><sex>m</sex></data><data><name>pedro</name><city>manila</city><age>22</age><sex>m</sex></data><data><name>maria</name><city>bangkok</city><age>23</age><sex>f</sex></data></person>`; 
    
      const xml=new DOMParser().parseFromString(txt,"text/html"),
        result=[...xml.querySelectorAll("data")].reduce((res,da)=>
          (res.push(atts.map(at=>da.querySelector(at).textContent)),res),
        []);
    // Test
      console.log(result);
    
    /* end of fetch(), uncomment next line for real application: */
    // });
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search