Reputation: 27
Some of the XML nodes is not always present in the XML feed, like gate and status, causing my code to break. This is my code:
$( document ).ready(function() {
$('#load_btn').click(function() {
loadXMLDoc();
});
});
function loadXMLDoc() {
$.ajax({
url: "proxy.php",
type: "POST",
dataType: "xml",
data: {
address: "http://flydata.avinor.no/XmlFeed.asp?TimeFrom=1&TimeTo=7&airport=OSL&direction=D&lastUpdate=2016-04-12T15:03:00Z"
},
})
.done(function (xml) {
var flightXML = $(xml).find('flight');
//console.log(flightXML);
var output = "<table>";
output += "<tr><th>Departue</th><th>Flight</th><th>To</th><th>Airline</th><th>Gate</th></tr>"
for(i=0; i < flightXML.length; i++)
{
var line = "<tr>";
var timeElement = flightXML[i].getElementsByTagName("schedule_time");
var time = timeElement[0].firstChild.nodeValue;
var idElement = flightXML[i].getElementsByTagName("flight_id");
var id = idElement[0].firstChild.nodeValue;
var toElement = flightXML[i].getElementsByTagName("airport");
var to = toElement[0].firstChild.nodeValue;
var airlineElement = flightXML[i].getElementsByTagName("airline");
var airline = airlineElement[0].firstChild.nodeValue;
var gateElement = flightXML[i].getElementsByTagName("gate");
var gate = gateElement[0].firstChild.nodeValue;
//var statusElement = flightXML[i].getElementsByTagName("status");
//var status = statusElement[0].firstChild.nodeValue;
line += "<td>" + time + "</td><td>" + id + "</td><td>" + to + "</td><td>" + airline + "</td><td>" + gate + "</td>";
line += "</tr>";
output += line;
}
output += "</table>";
document.getElementById("result").innerHTML = output;
});
}
This is the XML structure:
<flight uniqueID="5819145">
<airline>SK</airline>
<flight_id>SK815</flight_id>
<dom_int>I</dom_int>
<schedule_time>2016-04-12T18:15:00Z</schedule_time>
<arr_dep>D</arr_dep>
<airport>LHR</airport>
<check_in>7 8</check_in>
<gate>F19</gate>
</flight>
<flight uniqueID="5818372">
<airline>EW</airline>
<flight_id>EW4197</flight_id>
<dom_int>S</dom_int>
<schedule_time>2016-04-12T18:15:00Z</schedule_time>
<arr_dep>D</arr_dep>
<airport>HAM</airport>
<check_in>7</check_in>
<status code="C"></status>
</flight>
<flight uniqueID="5818645">
<airline>SK</airline>
<flight_id>SK291</flight_id>
<dom_int>D</dom_int>
<schedule_time>2016-04-12T18:15:00Z</schedule_time>
<arr_dep>D</arr_dep>
<airport>BGO</airport>
<check_in>7 8</check_in>
<gate>A4</gate>
</flight>
How can I check for presence of these nodes, and if not present, insert a blank space (or whatever is needed for my code not to break)?
Upvotes: 0
Views: 58
Reputation: 338316
You should separate your concerns better. Resist the temptation to write a function that does everything.
Let's abstract the plumbing for a proxied request into a function, complete with URL parameters that we can pass as an object.
function proxy(url, params) {
if (!params || typeof params !== "object") params = {};
return $.ajax({
type: "post",
url: "proxy.php",
data: {address: url + "?" + $.param(params)}
});
}
Remember to set the Content-Type
header in proxy.php
equal to the content type of the target page.
We want an array of flights, where each flight has the properties schedule_time, flight_id, airport, airline, gate
.
On top of that we want to pass in the query parameters (TimeFrom, TimeTo, airport, direction, lastUpdate
) in a structured way.
function getFlights(params) {
return proxy("http://flydata.avinor.no/XmlFeed.asp", params).then(function (xml) {
return $(xml).find('flight').map(function () {
var $flight = $(this);
return {
schedule_time: $flight.find("schedule_time").text(),
flight_id: $flight.find("flight_id").text(),
airport: $flight.find("airport").text(),
airline: $flight.find("airline").text(),
gate: $flight.find("gate").text()
};
}).toArray();
});
}
Using .then()
allows us to determine the overall result of the Ajax request, in our case it will be no longer XML but an array of uniform objects (no matter whether certain elements were missing in the XML).
We want to turn an array of flights into a table. I would recommend handlebars.js for HTML generation, but we can do it manually with jQuery as well:
function renderFlights(flights) {
var $table = $("<table>");
$table.append("<tr><th>Departue</th><th>Flight</th><th>To</th><th>Airline</th><th>Gate</th></tr>");
$.each(flights, function (i, flight) {
var $tr = $("<tr>").appendTo($table);
$("<td>", {text: flight.schedule_time }).appendTo($tr);
$("<td>", {text: flight.flight_id }).appendTo($tr);
$("<td>", {text: flight.airport }).appendTo($tr);
$("<td>", {text: flight.airline }).appendTo($tr);
$("<td>", {text: flight.gate }).appendTo($tr);
});
return $table;
}
Building HTML this way is safer than concatenating strings. It protects you against cross-site scripting attacks and random breakage due to unexpected special characters in the text.
Now we can bind a button click very easily like this:
$(function() {
$('#load_btn').click(function () {
getFlights({
TimeFrom: 1,
TimeTo: 7,
airport: "OSL",
direction: "D",
lastUpdate: "2016-04-12T15:03:00Z"
}).done(function (flights) {
var $table = renderFlights(flights);
$("#result").empty().append($table);
});
});
});
Upvotes: 1
Reputation: 3241
Depending on where it blows up, this might work:
var gateElement = flightXML[i].getElementsByTagName("gate");
var gate = gateElement[0].firstChild.nodeValue || "Gate not available";
I can't remember offhand if that would work. Might have to do:
var gate = "Gate not available";
var gateElement = flightXML[i].getElementsByTagName("gate");
if(gateElement) gate = gateElement[0].firstChild.nodeValue;
Upvotes: 0