不存在的XML节点破坏了我的脚本

时间:2016-04-12 18:09:08

标签: javascript xml dom

XML Feed中的某些XML节点并不总是存在,如门和状态,导致我的代码中断。这是我的代码:

$( 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;


    });
}

这是XML结构:

<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>

如何检查这些节点是否存在,如果不存在,请插入一个空格(或者我的代码不需要中断的任何内容)?

2 个答案:

答案 0 :(得分:1)

您应该更好地区分您的疑虑。抵制写一个能完成所有事情的功能的诱惑。

首先关注:请求代理

让我们将代理请求的管道抽象为函数,并使用我们可以作为对象传递的URL参数。

function proxy(url, params) {
    if (!params || typeof params !== "object") params = {};
    return $.ajax({
        type: "post",
        url: "proxy.php",
        data: {address: url + "?" + $.param(params)}
    });
}

请记住将Content-Type中的proxy.php标头设置为等于目标网页的内容类型。

第二个问题:从远程API获取数据

我们想要一系列航班,每个航班都有schedule_time, flight_id, airport, airline, gate个属性。

最重要的是,我们希望以结构化的方式传递查询参数(TimeFrom, TimeTo, airport, direction, lastUpdate)。

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();
    });
}

使用.then()允许我们确定Ajax请求的总体结果,在我们的例子中,它将不再是XML而是一组统一对象(无论XML中是否缺少某些元素)。 / p>

第三个问题:渲染

我们希望将一系列航班变成一张桌子。我建议handlebars.js用于HTML生成,但我们也可以使用jQuery手动完成:

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;
}

以这种方式构建HTML比连接字符串更安全。它可以保护您免受跨站点脚本攻击以及​​文本中意外特殊字符导致的随机破坏。

第四个问题:用户界面连线

现在我们可以非常轻松地绑定按钮点击:

$(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);
        });
    });
});  

答案 1 :(得分:0)

根据爆炸的位置,这可能有效:

var gateElement = flightXML[i].getElementsByTagName("gate");
var gate = gateElement[0].firstChild.nodeValue || "Gate not available";

如果可以的话,我无法记得。可能必须这样做:

var gate = "Gate not available";
var gateElement = flightXML[i].getElementsByTagName("gate");
if(gateElement) gate = gateElement[0].firstChild.nodeValue;