responseText可行,但responseXML始终为空。

5

我已经查看了这里可以找到的所有答案,但是无法解决这个问题。我很确定我没有漏掉任何明显的东西。

我正在尝试根据经纬度加载地图标记。问题在于当我尝试将 AJAX 响应作为 responseXML 返回时,它总是为空的,如果我使用 responseText,则可以正常工作,但显然下一步不起作用。

这是生成 XML 的 PHP 代码:

<?php
header('Content-type: text/xml');
?>    
<?xml version="1.0" encoding="ISO-8859-1"?>
<properties>
    <![CDATA[
<?php 
if ($body != null): 
        foreach ($body as $property): ?>
        <property>
            <lat><?php echo $property -> lat; ?></lat>
            <long><?php echo $property -> long; ?></long>
            <name><?php echo $property -> property_name; ?></name>
            </property>
<?php endforeach;
endif; ?>
    ]]>
</properties>

我可以在 Fiddler 中看到请求已经成功发送。

GET /letsgo/index.php/hotmaps/get_properties_ajax/22.270888501350186/22.288560098193066/114.13720860290528/114.19827713775635 HTTP/1.1

实体内容类型:text/xml

虽然在 Fiddler 的 XML 视图中查看时它似乎是空的,但这并不影响请求的成功。以下是原始响应内容。
HTTP/1.1 200 OK
Date: Tue, 15 Jan 2013 11:04:27 GMT
Server: Apache/2.4.2 (Win32) PHP/5.4.4
X-Powered-By: PHP/5.4.4
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 310
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/xml



<?xml version="1.0" encoding="ISO-8859-1"?>
<properties>
    <![CDATA[
        <property>
            <lat>22.2776</lat>
            <long>114.173</long>
            <name>Kaxo Tower test</name>
            </property>
        <property>
            <lat>22.2803</lat>
            <long>114.16</long>
            <name>Kuno Tower</name>
            </property>
    ]]>
</properties>

这里是创建标记的函数,每次地图移动时都会调用该函数。

// make the ajax request
function loadXMLDoc(downUrl){
    var xmlhttp;
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
      }
    else {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function() {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {

            //var propertiesXml = xmlhttp.responseText; // WORKS FINE!!
            var propertiesXml = xmlhttp.responseXML; // ALWAYS null
            //alert(propertiesXml);     
            var propertiesRows = propertiesXml.getElementsByTagName("property");

            for (var i = 0; i < propertiesRows.length; i++) {           
            var propertiesRow = propertiesRows[i];
            var xmlLat = propertiesRow.getElementsByTagName("lat")[0];
            var xmlLong = propertiesRow.getElementsByTagName("long")[0];
            var propertyLatLong = new google.maps.LatLng(parseFloat(xmlLat.firstChild.data),parseFloat(xmlLat.firstChild.data));            
            // create each marker
            createMarker(propertyLatLong);
            }   

        }
      }
    xmlhttp.open("GET", downUrl, false); // false or true? makes no difference
    xmlhttp.setRequestHeader("Content-type", "text/xml");
    xmlhttp.send(); 
}

以下是在Chrome控制台中使用getElementsByTagName(null)时出现的错误信息:

Uncaught TypeError: Cannot call method 'getElementsByTagName' of null

此代码正在我的本地Apache上运行。

是否有建议?

/** 更新 - 已工作代码 **/

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
      html { height: 100% }
      body { height: 100%; margin: 0; padding: 0 }
      #map_canvas { height: 100% }
    </style>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=APIKEYHERE&sensor=false">
    </script>

    <script type="text/javascript">  

      // initialise map 
      function initialize() {

      // set starting latlong
      var myLatlng = new google.maps.LatLng(22.2776, 114.173); 

      // set initial map options        
      var mapOptions = {
        center: myLatlng,
        zoom: 13,
        mapTypeId: google.maps.MapTypeId.ROADMAP
        };

      // create the map                       
      var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); 

      // listen for changes in map bounds - after map has stopped moving!!      
      google.maps.event.addListener(map,'idle', function () {      
        loadByBounds(map);          
        });                 
      }

      // if the bounds have changed 
      function loadByBounds(map) {  

        var bounds = map.getBounds();       
        var swPoint = bounds.getSouthWest();
        var nePoint = bounds.getNorthEast();

        // specific co ordinates
        var swLat = swPoint.lat();
        var swLng = swPoint.lng();
        var neLat = nePoint.lat();
        var neLng = nePoint.lng();               

        var downUrl = "<?php echo site_url('hotmaps/get_properties_ajax'); ?>/"+swLat+"/"+neLat+"/"+swLng+"/"+neLng;

        // load the 
        loadXMLDoc(downUrl, map); 

        // clear icons outside of bounding box

        //....


        }

        // make the ajax request
        function loadXMLDoc(downUrl, map){
            var xmlhttp;
            if (window.XMLHttpRequest) {
                // code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp=new XMLHttpRequest();
              }
            else {// code for IE6, IE5
              xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
              }
            xmlhttp.onreadystatechange=function() {
              if (xmlhttp.readyState==4 && xmlhttp.status==200)
                {

                    var propertiesXml = xmlhttp.responseText; // WORKS FINE!!

                    // remove whitespaces from start and end (.trim() doesnt work)
                    propertiesXml = propertiesXml.replace(/^\s+|\s+$/g,'');                 

                    // manually parse to XML DOM object 
                    var parser = new DOMParser();                   
                    var xmlDoc;                 
                       try {
                            xmlDoc = parser.parseFromString (propertiesXml, "text/xml");
                        } catch (e) {
                            alert ("XML parsing error.");
                            return false;
                        };

                    //console.log(xmlDoc);

                    // get each property
                    var propertiesRows = xmlDoc.getElementsByTagName("property");   

                    //alert(console.log(propertiesRows));   
                    for (var i = 0; i < propertiesRows.length; i++) {

                        var propertiesRow = propertiesRows[i];
                        var xmlLat = propertiesRow.getElementsByTagName("lat")[0];
                        var xmlLong = propertiesRow.getElementsByTagName("long")[0];
                        var propertyLatLong = new google.maps.LatLng(parseFloat(xmlLat.firstChild.data),parseFloat(xmlLong.firstChild.data));           
                        // create each marker
                        createMarker(propertyLatLong, map);
                    }
                 }
             }
            xmlhttp.open("GET", downUrl, false);
            xmlhttp.setRequestHeader("Content-type", "text/xml");
            xmlhttp.send(); 
        }   

        // create new markers
        function createMarker(propertyLatLong, map){             
            var dynamicMarker = new google.maps.Marker({

                map:map,
                draggable:false,
                position: propertyLatLong
            });
            debugger;           
        }       
    </script>
  </head>
  <body onload="initialize()">      
    <div id="map_canvas" style="width:100%; height:100%"></div>
  </body>
</html>
3个回答

7

您可以尝试自己解析XML:

var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml");

Like this.


我已经按照你建议的路线走了,似乎已经起作用了,但现在我遇到了一个未定义变量错误,这可能是一个单独的问题,你介意看一下吗?谢谢。 - user74847
你能更具体一些吗?哪个变量未定义在哪一行? - povilasp
Â未定义 fullscreen:104,这将是.. } } xmlhttp.open("GET", downUrl, false); - user74847
1
不知何故,字符Â已经进入了第104行,在aptana中看不到,即使删除了所有未定义的Â字符,我在记事本中打开文件,它就出现了。删除它后一切正常 :) - user74847

0

我想知道为什么你希望解析器跳过几乎整个HTTP响应体,似乎没有必要,因为它不包含任何可能被误解的内容。甚至是你想要解析的数据,在你的示例中却无缘无故地隐藏起来。

在这里查看一些CDATA的解释:http://www.w3schools.com/xml/xml_cdata.asp

你可以尝试像这里提到的那样注释掉开头和结尾的CDATA语句:http://de.selfhtml.org/html/xhtml/unterschiede.htm

他们还指出,XML解析器默认假定UTF-8编码,并且如果配置不正确,将拒绝解析,并且不建议通过响应头覆盖预期类型。

我更喜欢避免在块语句内部打开和关闭php块,但我对最新的编码约定不太了解,所以我可能在这方面有所错误。

<?php

header('Content-type: text/xml');
header ('Cache-Control: no-cache');
header ('Cache-Control: no-store' , false);

$response ='<?xml version="1.0" encoding="UTF-8"?>
<properties>';

if ($body != null): 
    foreach ($body as $property):
        $response .='<property>
            <lat>'.$property->lat.'</lat>
            <long>'.$property->long'.</long>
            <name>'.$property->property_name.'</name>
        </property>';
    endforeach;
endif;

$response .='</properties>';

echo responseText;

?>

好的,谢谢!如果视图文件中有很多HTML,我发现按照我所做的方式编写更容易阅读,也更容易找到HTML中的错误! - user74847

0

你的标签在CDATA部分,因此解析器将其作为标记忽略。


我在阅读了类似帖子上某人的回复后添加了CDATA,但并没有任何区别。 - user74847
看一下这个链接:http://www.w3.org/TR/REC-xml/#dt-cdsection 和 Lemmy Tauer 发布的链接。 - JEY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接