javascript responseText 有效,但 responseXML 始终为空

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14336381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 21:20:57  来源:igfitidea点击:

responseText works but responseXML is always null

phpjavascriptxmlajaxgoogle-maps

提问by dijkstra8x

I've looked through every answer i can find on here and can't solve this. I'm pretty sure I havn't missed anything obvious.

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

I'm trying to load map markers based on lat longs. The problem is when I try to return the AJAX response as responseXML its always null, if i use responseText it works fine but obviously the next step doesn't work.

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

This is the PHP that generates the XML:

这是生成 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>

I can see in Fiddler that the request is made ok

我可以在 Fiddler 中看到请求已完成

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

Entity Content-type: text/xml

GET /letsgo/index.php/hotmaps/get_properties_ajax/22.270888501350186/22.288560098193066/114.13720860290528/114.1982775137775633

实体内容类型:text/xml

Although when i view this in XML view in fiddler it appears to be empty,

虽然当我在 fiddler 的 XML 视图中查看它时,它似乎是空的,

here is the raw response

这是原始回复

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>

Here is the create marker function that is called every time the map is moved

这是每次移动地图时调用的创建标记函数

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

and this is the error i get for feeding getElementsByTagName with null, Chrome console says

Chrome 控制台说,这是我为 getElementsByTagName 提供 null 时得到的错误

Uncaught TypeError: Cannot call method 'getElementsByTagName' of null

未捕获的类型错误:无法调用 null 的方法“getElementsByTagName”

This is running on my local Apache

这是在我本地的 Apache 上运行

Any suggestions?

有什么建议?

/** UPDATE - WORKING CODE **/

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

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

回答by povilasp

You can try parsing XML yourself:

您可以尝试自己解析 XML:

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

Like this.

像这样。

回答by JEY

your tags are in CDATA section so they are ignore as tag by the parser.

您的标签位于 CDATA 部分,因此解析器将它们作为标签忽略。

回答by Lemonade

I wonder why you want the parser to skip almost your entire http response body, it seems there is no need, it's not containing anything that could be misinterpreted. It even is the data you want to get parsed, that you hideaway in your example for no apparent reason.

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

Look here for some explanation of CDATA: http://www.w3schools.com/xml/xml_cdata.asp

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

You could try commenting out the opening and closing CDATA statement like mentioned here: http://de.selfhtml.org/html/xhtml/unterschiede.htm

您可以尝试注释掉这里提到的打开和关闭 CDATA 语句:http: //de.selfhtml.org/html/xhtml/unterschiede.htm

They also state, that the XML parser assumes UTF-8 encoding by default and will refuse parsing if not configured correctly, and that overwriting the exspected type via the response header is not recommended.

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

I prefer to avoid opening and closing php blocks inside block-statements the way you did it, but I'm not quite up-to-date with the latest coding conventions, so I may be wrong on that one.

我更喜欢避免像您那样在块语句中打开和关闭 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;

?>