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." },
],
});
},
});
});
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: */
// });
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>
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.
Related
I have an XML which I am parsing using jquery, it works but I want to only get part of the XML data and then save all that part in localstorage.
My xml looks like this
<channel id="123"><display-name>123</display-name></name></channel>
<channel id="123"><display-name>123</display-name></name></channel>
<channel id="123"><display-name>123</display-name></name></channel>
<programme id="123"><display-name>123</display-name></name></programme>
<programme id="123"><display-name>123</display-name></name></programme>
<programme id="123"><display-name>123</display-name></name></programme>
But I only want to get all the <programme> data and then save that to localstorage. Im not sure how I can only grab the programme sections.
I have tried saving the whole xml but that didnt seem to output any data. This is what what I have tried.
<div id="text"></div>
$(function(){
$.ajax({
type: "GET",
url: "/myxml",
dataType: "xml",
success: function(xml){
window.localStorage.setItem('fullxml', xml)
$("#text").append(window.localStorage.getItem('fullxml'));
},
error: function() {
alert("An error occurred while processing XML file.");
}
});
});
To get a specific node from an XML document, you can select the XML node like this:
Javascript:
var programmeNodes = fullxml.getElementsByTagName('programme');
jQuery:
var programmeNodes = $(fullxml).find('programme');
My Solution:
This solution grabs all <programme> nodes and saves the data into an array and then stores that array in local storage for later use.
Given XML data like this:
var xml = `
<programmes>
<programme id="1">
<display-name>Test 1</display-name>
</programme>
<programme id="2">
<display-name>Test 2</display-name>
</programme>
</programmes>
`;
Will give an array of objects like this which can then be stored.
[
{
id: 1,
name: Test1
},
{
id: 2,
name: Test2
}
]
Full demo code:
var xml = `
<programmes>
<programme id="1">
<display-name>Test 1</display-name>
</programme>
<programme id="2">
<display-name>Test 2</display-name>
</programme>
</programmes>
`;
var fullxml = $.parseXML(xml);
// find <programme> XML elements
var programmeNodes = $(fullxml).find('programme');
// create array for programme data
var programmesArr = [];
// loop through each programme and store data in array
$.each(programmeNodes, function(i) {
var programmeID = $(programmeNodes[i]).attr('id');
var programmeDisplayName = $(programmeNodes[i]).find('display-name').text();
programmesArr.push({
id: programmeID,
name: programmeDisplayName
});
});
// store programmesArr in local storage
// localStorage only allows strings, so we need to convert array to JSON string
localStorage.setItem('programmes', JSON.stringify(programmesArr));
// get programmes from local storage
var storedProgrammes = JSON.parse(localStorage.getItem('programmes'));
DEMO: https://jsfiddle.net/1nLw7hjr/13/
Usage:
var programmeToFind = 2;
var programme = $.grep(storedProgrammes, function(e) {
return e.id == programmeToFind;
});
console.log(programme[0].id); // 2
console.log(programme[0].name); // Test2
Or as a little function:
function searchProgrammes(id) {
var programme = $.grep(storedProgrammes, function(e) {
return e.id == id;
});
return programme[0];
}
var programme = searchProgrammes(2);
console.log(programme.id); // 2
console.log(programme.name); // Test2
grep()
Finds the elements of an array which satisfy a filter function. The
original array is not affected.
I think you don't get any response because when you append the XML to the document, the browser try to parse it, and because this isn't valid HTML, it fails and show only the text, not the tags. So, the simplest solution will to not use jQuery's append() method, and instead, append the XML via text() (that doesn't parse the HTML tags, and instead escapes them), like:
$(function() {
$.ajax({
type: "GET",
url: "/myxml",
dataType: "xml",
success: function(xml) {
window.localStorage.setItem('fullxml', xml);
var el = $("#text");
el.text(el.text() + window.localStorage.getItem('fullxml'));
},
error: function() {
alert("An error occurred while processing XML file.");
}
});
});
Edit:
If you want to store only some elements, you should convert the XML to objects. Use DOMParser, as follows:
$(function() {
$.ajax({
type: "GET",
url: "/myxml",
dataType: "xml",
success: function(xml) {
var xmldoc;
if (window.DOMParser) {
parser = new DOMParser();
xmldoc = parser.parseFromString(xml, "text/xml");
} else { // Internet Explorer
xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.async = false;
xmldoc.loadXML(xml);
}
var programmes = xmldoc.getElementsByTagName('programme');
var str = '';
programmes.forEach(function(el) {
str += el.outerHTML;
});
// str now contains only the <programme> elements
window.localStorage.setItem('fullxml', str);
var el = $("#text");
el.text(el.text() + window.localStorage.getItem('fullxml'));
},
error: function() {
alert("An error occurred while processing XML file.");
}
});
});
i have a simple XML file which is loaded on page by a script posted below. It converts from a string to a XML file without any problems, but what complicates everything is the fact, that I can't get to a child's child.
I'd like to know why my code doesn't work and what should I do to get the tag name.
function load_xml() {
$.ajax({
type: "GET",
url: "file.xml",
dataType: "xml",
success: function (xmlData) {
var $first_child = $(xmlData).children()[0];
var first_name = $first_child.nodeName; // returns a proper name of a node
var $second_child = $first_child.children()[0]; // doesn't work
var $second_name = $second_child.nodeName; // returns nothing (don't know why)
},
error: function () {
alert("Could not retrieve XML file.");
}
});
}
In your case $first_child is not a jQuery collection. You need to wrap it with $(). Here is a corrected version.
var first_child = $(xmlData).children()[0]; // [0] actually returns the first "raw" node
var first_name = first_child.nodeName;
var $first_child = $(first_child);
var second_child = $first_child.children()[0];
var second_name = second_child.nodeName;
I have a places.php file on my server that returns the following json:
{"places":[{"poi_id":"1","poi_latitude":"53.9606","poi_longitude":"27.6103","poi_title":"Shop1","poi_category":"Shopping","poi_subcategory":"Grocery Store","poi_address":"Street 1, 1","poi_phone":null,"poi_website":null},{"poi_id":"2","poi_latitude":"53.9644","poi_longitude":"27.6228","poi_title":"Shop2","poi_category":"Shopping","poi_subcategory":"Grocery Store","poi_address":"Street 2","poi_phone":null,"poi_website":null}]}
In my javascript I use the following piece of code:
$(document).ready(function() {
var url="places.php";
$.getJSON(url,function(data){
$.each(data.places, function(i,place){
var new1 = place.poi_id;
alert(new1);
});
});
});
However the message box with the poi_id doesn't pop up. What am I doing wrong?
How about like this.
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
// data source
var jsonStr = '{"places":[{"poi_id":"1","poi_latitude":"53.9606","poi_longitude":"27.6103","poi_title":"Shop1","poi_category":"Shopping","poi_subcategory":"Grocery Store","poi_address":"Street 1, 1","poi_phone":null,"poi_website":null},{"poi_id":"2","poi_latitude":"53.9644","poi_longitude":"27.6228","poi_title":"Shop2","poi_category":"Shopping","poi_subcategory":"Grocery Store","poi_address":"Street 2","poi_phone":null,"poi_website":null}]}';
// parse json string to object
var jsonObj = JSON.parse(jsonStr);
// usage 1
console.log('iterate - without jQuery');
for (var i = 0; i < jsonObj.places.length; i++)
{
var place = jsonObj.places[i];
console.log(place.poi_id);
}
// usage 2
console.log('iterate - with jQuery');
$(jsonObj.places).each(function(index, place)
{
console.log(place.poi_id);
});
</script>
Output:
How to use this in your code:
$(document).ready(function()
{
$.getJSON("/path/to/places.php", function(data)
{
// data here will be already decoded into json object,
// so... you do this
$(data.places).each(function(index, place)
{
console.log(place.poi_id);
});
});
});
Take a look at the manual also: http://api.jquery.com/jquery.getjson/
Should work, if not leave a comment with an error or reason.
Does this do / get you closer:
for (var property in data)
{
if (data.hasOwnProperty(property))
{
console.log(property);
}
}
Is your php actually generating the JSON? If it's only getting a particular file it may be easier to choose your file using JS and AJAX it. Here's the code I use for php anyway.
function callPHP(dataToSend)
{
$.post( "places.php", dataToSend )
.done(function( phpReturn ) {
console.log( phpReturn );
var data = JSON.parse(phpReturn);
for(var i = 0;i<data.places.length;i++)
console.log(data.places[i].poi_id);
});}
}
Setting places.php file encoding to UTF-8 solved the problem
I have a page where I want to add couple of controls
when I click on 1st control, I want my javascript to open particular JSONpage, gram the content and then output the content in specific <DIV id="one">. Then, when I select some of the elements in div id="one", I want The JavaScript to connect to another JSON page and get another array of data from there.
My question - how do I do the JSON part?
In other words, how do I get JavaScript version of:
$dataSet = json_decode(file_get_contents($url), true);
I am new to JavaScript and this thing takes so much time!!
Got this working
function getDates() {
jQuery(function($) {
$.ajax( {
url : "jsonPage.php",
type : "GET",
success : function(data) {
// get the data string and convert it to a JSON object.
var jsonData = JSON.parse(data);
var date = new Array();
var i = -1;
$.each(jsonData, function(Idx, Value) {
$.each(Value, function(x, y) {
if(x == 'date')
{
i = i + 1;
date[i] = y;
}
});
});
//output my dates; [0] in this case
$("#testArea").html(date[0]);
}
});
});
}
How can I count the number of leaf nodes coming off a particular XML node using jQuery?
The XML in question looks similar to this. I want all leaf nodes coming off the <Errors> node.
<Errors>
<ErrorParentCat>
<ErrorTag/>
<ErrorTag2/>
</ErrorParentCat>
</Errors>
In this example I want <ErrorTag/> and <ErrorTag2/> counted only. The result should therefore be 2. Also <ErrorParentCat> is an example tag, there could be many within <Errors> with different names.
Once I have the number I would like a list of these leaf nodes too, if possible.
Assuming you already have an XMLDocument named xml:
var $xml = $(xml),
count = $xml.find('*').filter(function ()
{
return $(this).children().length === 0;
}).length;
console.log(count);
You can also just pass the XML string directly to the jQuery function:
var $xml = $('<Errors><ErrorParentCat><ErrorTag/><ErrorTag2/></ErrorParentCat></Errors>');
// the rest is the same
jsfiddle demo →
Edit you said you wanted a list of those leaf nodes. In the code above, you've already got them:
var $xml = /* whatever */,
$leafNodes = $xml.find('*').filter(function ()
{
return $(this).children().length === 0;
}),
count = $leafNodes.length;
Edit #2 as Tim Down has pointed out (see comments below), you cannot just pass the XML string to $() in IE (!##$ing IE). You should use the jQuery 1.5 function $.parseXML() to parse an arbitrary well-formed XML string into an XMLDocument:
var xmlDoc = $.parseXML('<Errors><ErrorParentCat><ErrorTag/><ErrorTag2/></ErrorParentCat></Errors>'),
$xml = $(xmlDoc);
/* the rest is unchanged */
new jsfiddle demo →
Loads of ways to do this:
var countThem = 0;
jQuery.ajax({
type: "GET",
url: 'blahblah.xml',
dataType: ($.browser.msie) ? "text/xml" : "xml",
success: function(xml) {
var xml2 = load_xml(xml);
$(xml2).find('Errors').each(function(){
$(xml2).find('ErrorParentCat').each(function(){
alert($(this).text()); //alert the contents
countThem++;
});
});
alert(countThem); //alert the total number
}
});
and the XML load function:
function load_xml(msg) {
if ( typeof msg == 'string') {
if (window.DOMParser)//Firefox
{
parser=new DOMParser();
data=parser.parseFromString(text,"text/xml");
}else{ // Internet Explorer
data=new ActiveXObject("Microsoft.XMLDOM");
data.async="false";
data.loadXML(msg);
}
} else {
data = msg;
}
return data;
}