ResponseText works, but responseXML is always null

I looked through every answer that I can find here and cannot solve it. I am pretty sure that I did not miss anything obvious.

I am trying to load map markers based on long long. The problem is that when I try to return an AJAX response, since responseXML is always null, if I use responseText, it works fine, but obviously the next step doesn't work.

This is the PHP that generates the XML:

<?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 see in Fiddler that the request is made ok

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

Entity Content-type: text / xml

Although, when I look at this in an XML representation in a creak, it seems empty,

here is the original answer

 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, which is called every time the map moves.

 // 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 to load getElementsByTagName with a null value, the Chrome console reports

Uncaught TypeError: cannot call getElementsByTagName method from null

This works on my local Apache

Any suggestions?

/ ** UPDATE - WORK 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> 
+5
source share
3 answers

You can try to parse the XML yourself:

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

Like this.

+7
source

your tags are in the CDATA section, so they are ignored as a tag by the parser.

0
source

I wonder why you want the parser to skip almost all of your HTTP response block, it seems that there is no need, it does not contain anything that could be misinterpreted. This is even the data that you want to parse that you hide in your example for no apparent reason.

Check out some CDATA explanation here: http://www.w3schools.com/xml/xml_cdata.asp

You can try to comment on the CDATA open and close expression, as indicated here: http://de.selfhtml.org/html/xhtml/unterschiede.htm

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

I prefer not to open and close php blocks inside statement blocks the way you did, but I'm not completely updated with the latest coding conventions, so I could be wrong about that.

 <?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; ?> 
0
source

Source: https://habr.com/ru/post/907276/


All Articles