2

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 Answers3

1

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: */
// });
Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • how can I assign the result variable outside the fetch() function? I tried using return result and then declared var dataSet = fetch(). i then used dataSet as data source on my DataTable but it did not work. – randomnamesksksk Oct 09 '22 at 12:19
  • This is a typical question with regards to asynchronous processing, see for answers here: https://stackoverflow.com/a/38869587/2610061 – Carsten Massmann Oct 09 '22 at 12:27
0

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>
tarkh
  • 2,424
  • 1
  • 9
  • 12
  • how should I use the $.parseHTML(xml) when my xml is from a separate xml file? – randomnamesksksk Oct 09 '22 at 11:59
  • You passing data to your `writeperson` function as `xml` variable, use it. You can try to put all this code inside `writeperson` function. Maybe you need to ectract `xmlDoc = xml.responseXML;` before and use `xmlDoc` instead, do some tests. – tarkh Oct 09 '22 at 12:20
  • Or use `$.ajax` to read your `xml` file, like this: https://stackoverflow.com/a/19220964/10917379 – tarkh Oct 09 '22 at 12:29
0

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.

Twisty
  • 30,304
  • 2
  • 26
  • 45
  • I declared var dataSet = xmlToArray(xml); and then used the dataSet variable on my data table as data source but it seems like datatable does not recognize it. It shows an array on my page but the datatable is not applied – randomnamesksksk Oct 09 '22 at 12:10
  • @randomnamesksksk how are you passing the Array to the Datatables? Please provide a Minimal, Reproducible Example: https://stackoverflow.com/help/minimal-reproducible-example – Twisty Oct 10 '22 at 04:46