cannot parse a url from xml file in javascript - javascript

I'm trying to parse an xml file . I'm using the function downloadUrl . The element <link> of my xml file contains a url with ' & ' ( ampersant character ) . The error in my browser says : " Cannot read property 'documentElement' of null " I replace the & with & in a sample file-similar to my xml and the parse runs great!One important information : I cannot edit my xml file .
So , the solution is to insert at the javascript code a function to replace this character & with & .Something like that i imagine:
function htmlEscape(items) {
return String(items)
.replace(/&/g, '&');
}
But i cannot find the way on how to do that.
Here's is my script :
var infowindow;
var map;
function initialize() {
var myLatlng = new google.maps.LatLng(38.822590,24.653320);
var myOptions = {
zoom: 6,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
downloadUrl("moredata.xml", function(doc) {
var items = doc.documentElement.getElementsByTagName("item");
for (var i = 0; i < items.length; i++) {
var description = items[i].getElementsByTagName("description")[0].textContent;
var temp = items[i].getElementsByTagName("temp")[0].textContent;
var title = items[i].getElementsByTagName("title")[0].textContent;
var link = items[i].getElementsByTagName("link")[0].textContent;
var latlng = new google.maps.LatLng(parseFloat(items[i].getElementsByTagName("glat")[0].textContent),
parseFloat(items[i].getElementsByTagName("glon")[0].textContent));
a part of my xml :
<channel>
<title>
Real time weather in Greece
</title>
<link>http://www.123.gr/</link>
<image>
<url>
http://www.123.gr/templates/metar/images/metar.gif
</url>
<title>123.gr</title>
<link>http://www.123.gr/</link>
</image>
<description>
Real time weather in Greece
</description>
<language>el</language>
<pubDate>Thu, 03 Apr 2014 17:08:10 +0300</pubDate>
<copyright>123.gr</copyright>
<managingEditor>kondilis#123.gr</managingEditor>
<webMaster>admin#123.gr</webMaster>
<item>
<title>Center</title>
<description>Salonica</description>
<link>
http://www.metar.gr/index.php?option=com_jumi&fileid=12&Itemid=73&station=1227
</link>
<temp>16.7 °C</temp>
<glat>40.422726139672626</glat>
<glon>22.93392777442932</glon>
</item>
</channel>
the downloadUrl function :
function downloadUrl(url, callback) {
var status = -1;
var request = createXmlHttpRequest();
if (!request) {
return false;
}
request.onreadystatechange = function() {
if (request.readyState == 4) {
try {
status = request.status;
} catch (e) {
// Usually indicates request timed out in FF.
}
if (status == 200) {
callback(request.responseXML, request.status);
request.onreadystatechange = function() {};
}
}
}
request.open('GET', url, true);
try {
request.send(null);
} catch (e) {
changeStatus(e);
}
};

The problem is that responseXML is broken because of an invalid XML document, it's not just an invalid string. You will probably have to retrieve the responseText, replace the ampersands with properly encoded entities and then do something like the solutions to this SO question to make that string into a traversable XML document

Related

express routing triggers: "Can't set headers after they are sent." error

I am new to Express, and having trouble sending data from backend to front end. Here is what I want to do: I have a Google Map API on the homepage (home.ejs). app.js is the server code: when the homepage is loaded, app.js generate some random locations and send to home.ejs, so home.ejs use those locations as Markers. Now I want to add an event listener to each of these Markers, so that when the mouse is over the Marker, it sends a GET request to server, to request a picture to display.
I feel it a big challenge for me to send the request/data back and forth. When the mouse is over, the home.ejs sends a GET Request to /getImage/:num route, and app.get("/getImage/:num", function(req, res){}) responds to that request by retrieving the image url, and redirect to "/" and sends the url to it. This is where I get the "Can't set headers after they are sent".
I am so new to Express and ejs that I don't even know if I am on the right track. How should I implement this to get the communication through?
This is the app.js server file
var express = require("express");
var app = express();
//app.use(express.static(__dirname + "/public"));
app.use(express.static(__dirname));
app.set("view engine","ejs");
var lng_min = -84.161;
var lng_max = -83.688;
var lat_min = 35.849;
var lat_max = 36.067;
var urls = [
"http://cdn1-www.dogtime.com/assets/uploads/2015/01/file_21032_the-most-popular-dog-and-cat-names.jpg",
"http://qltyctrl.com/wp-content/uploads/2014/03/Sad-Dog-and-Cat.jpg",
"https://blog-photos.dogvacay.com/blog/wp-content/uploads/2015/07/dog-cat-smarter-ftr.jpg",
"http://qltyctrl.com/wp-content/uploads/2014/03/Dog-and-Cat-on-a-Log.jpg",
"http://images.boomsbeat.com/data/images/full/31730/cat-and-dog_1-jpg.jpg",
"http://www.vetlocator.com/dailypaws/wp-content/uploads/2012/04/dog-cat2.jpg",
"http://qltyctrl.com/wp-content/uploads/2014/03/Old-Dog-and-Cat-Sleepy-Embrace.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXNMdvNfc3WYMqbPrJrnjgHJRp2zB1y9vx545LfO-_U5_yvgBo",
"http://www.vetlocator.com/dailypaws/wp-content/uploads/2012/04/dog-cat8.jpg",
"http://www.maddiesfund.org/assets/metaImage/robust-dog-cat-foster.jpg"
]
var numLocations = 10;
var data = [];
function generateData() {
// generate random locations and the url to download pictures
for (var i = 0; i < numLocations; ++i) {
var lng = Math.random() * (lng_max - lng_min) + lng_min;
var lat = Math.random() * (lat_max - lat_min) + lat_min;
var tuple = {
id: i,
lng: lng,
lat: lat,
pic: urls[i]
};
data.push(tuple);
}
}
app.get("/", function(req, res) {
//res.send("Hello it works");
data = [];
generateData();
res.render("home.ejs", {data: data});
});
app.get("/getImg/:num", function(req, res) {
console.log(req.params.num);
var i = Number(req.params.num);
res.redirect("/");
res.send({imgUrl: data[i].pic});
});
app.listen(process.env.PORT, process.env.IP, function() {
console.log("Server Started!");
});
home.ejs file:
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<link rel="stylesheet" type="text/css" href="/public/app.css">
</head>
<body>
<div id="map">
</div>
<script>
var data = <%- JSON.stringify(data) %>;
console.log(data.length);
function initMap() {
var loc = {lat: 35.9606, lng: -83.9207};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: loc
});
for (var i = 0; i < data.length; ++i) {
var loc = {lat: data[i].lat, lng: data[i].lng};
var marker = new google.maps.Marker({
position: loc,
map: map
// id: i
});
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, 'mouseover', (function(marker) {
return function() {
// var content = '<div id="imgDisplay">'
// + '<img src="http://www.maddiesfund.org/assets/metaImage/robust-dog-cat-foster.jpg">'
// + '</div>';
// infowindow.setContent(content);
// infowindow.open(map, marker);
var xhr = new XMLHttpRequest();
var params = 3;
xhr.open('GET','/getImg/'+params, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(responseText);
}
}
//xhr.send(params);
xhr.send();
}
})(marker));
}
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAOwfkV_GbUXyH2s8iD0gS6pje9J3R96dM&callback=initMap">
</script>
</body>
</html>
You misunderstand the purpose of redirect. Express's redirect function says, "This path does not have an answer; instead try sending a request to this other path and see what it says." (This is done by a 3xx response like 301 or 302.)
Your confusion is that you think you need to tell the client which page should render the given URL. But that is not necessary: the server doesn't tell the client how to render the data it sends. The server just sends data, and the client decides what to do with it.
The good news is that your client-side JavaScript is doing its job correctly. It's using an XMLHttpRequest to fetch data from the server. Simply have the server actually send that data with the send function and don't call redirect. Once your client-side has the URL to load, you can load it in an <img> element with
var img = new Image();
img.src=responseText;
document.body.appendChild(img);
inside your onreadystatechange listener. You can use document.getElementById(...)
to get a different element if you don't want to add the element to your body.

Urls in creating chrome extension tabs do not work

I am creating a chrome extension which access a api and parses the json feed to get data. One of the data is a link and I want the link to be opened in a new tab. I use chrome.create.tabs to do it. But instead of opening a tab with specified url it opens like this
chrome-extension://app_id/%22http://www.twitch.tv/imaqtpie%22
Here is my popup.js
document.addEventListener('DOMContentLoaded', init);
function init(){
var elem = document.getElementById('Add');
elem.addEventListener('click',func);
}
function func(){
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.twitch.tv/kraken/search/streams?q=league%20of%20legends", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// innerText does not let the attacker inject HTML elements.
var qtpie=JSON.parse(xhr.responseText);
var display_name = JSON.stringify(qtpie.streams[0].channel.display_name);
var stream_status = JSON.stringify(qtpie.streams[0].channel.status);
var stream_url=JSON.stringify(qtpie.streams[0].channel.url);
var res = display_name+" : "+stream_status+"\n"+stream_url;
console.log(stream_url);
var a = document.createElement('a');
var linkText = document.createTextNode(res);
a.appendChild(linkText);
a.setAttribute('href', stream_url);
a.addEventListener('click', link_handler(stream_url));
document.getElementById("status").appendChild(a);
var magic=activateLinks();
// document.getElementById("status").innerText = res;
}
}
xhr.send();
}
function activateLinks()
{
var links = document.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
(function () {
var ln = links[i];
var location = ln.href;
ln.onclick = function () {
chrome.tabs.create({active: true, url: location});
};
})();
}
}
function link_handler(url)
{
// Only allow http and https URLs.
if (url.indexOf('http:') != 0 && url.indexOf('https:') != 0) {
return;
}
chrome.tabs.create({url: url});
}
Here stream_url is the variable that stores the parsed url from json.
here is the json from which it is parsed from
"video_banner":null,
"background":null,
"profile_banner":null,
"profile_banner_background_color":null,
"partner":true,
"url":"http://www.twitch.tv/imaqtpie",
"views":91792487
i want the new tab to open http://www.twitch.tv/imaqtpie instead of chrome-extension://app_id/%22http://www.twitch.tv/imaqtpie
. Thanks in advance. Btw using <base href="http://" target="_blank"> does not work.
So the problem is for the url. Your url is improper when using chrome.tabs.create, because %22 indicates the character " in ASCII Encoding Reference. You should strip it off in the url when you get the element in html. Glad it helps!

Passing a javascript variable to a php file that creates XML

I am new here but use thee forums daily, so please forgive any etiquette errors! My question is actually very similar to this post Dynamically update variables in external PHP XML generation script . I need to pass a user input from a js var to a php script to query a db to then create an XML. I can get the file to work hardcoded. The ajax call I am using works in that it will pass a var to php using $_get, but it cant seem to output an XML file if I then try to use the passed variable unless it is hardcoded; I have this file working perfeclty in another context with hardcoded sql query. I am not sure if the query is not being passed correctly in the get method or not? maybe the code will help explain my issue a little better.
downloadUrl("XML.php"+queryString, function(data){
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var type = markers[i].getAttribute("type");
var address = markers[i].getAttribute("address");
//var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + type + "</b> <br/>" + address;
var icon = "http://maps.google.com/mapfiles/kml/pal4/icon52.png";
var title = markers[i].getAttribute("address")+ ' Fatalities: ' +markers[i].getAttribute("deaths");
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon,
title: title
});
bindInfoWindow(marker, map, infoWindow, html);
}
});//downloadUrl
}//load
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
var type = document.getElementById('confType').value;
var queryString ="?type=" + type;
request.open('GET', "XML.php"+queryString, true);
var params='type='+type;
request.send(params);
}
function doNothing() {}
<?php
$type = $_GET['type'];
//$type='RiotsProtests';
//$type= mysql_real_escape_string($type);
require("phpsqlajax_dbinfo.php");
$query = "SELECT * FROM incident WHERE EVENT_TYPE = `$type`"; //<-------------||||||
$result = mysql_query($query);
if (!$result) {die('Invalid query: ' . mysql_error());}
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
header("Content-type: text/xml");
($row = #mysql_fetch_assoc($result)){
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("type",$row['EVENT_TYPE']);
$newnode->setAttribute("address", $row['LOCATION']);
$newnode->setAttribute("lat", $row['LATITUDE']);
$newnode->setAttribute("lng", $row['LONGITUDE']);
$newnode->setAttribute("deaths", $row['FATALITIES']);
$newnode->setAttribute("actor1", $row['ACTOR1']);
$newnode->setAttribute("actor2", $row['ACTOR2']);
}
echo $dom->saveXML();
?>
I have tried putting in the queryString, using SESSION_vars, but nothing seems to work. Whenever i call the XML file, it doesnt seem to output anything, like the xml isnt properly getting populated. When i change the header to xml/plain, i get proper output from a hardcode query, but the xml process does not seem to like the variable. please help!!

Javascript and XML

I am working on JavaScript using HTML5 and I am stuck with a certain aspect. I want to do the following:
Create a table using JavaScript (which is fairly easy)
Extract details from a XML file that is available online
Enter the values in the table
For example, the linkhttp://www.tfl.gov.uk/tfl/syndication/feeds/cycle-hire/livecyclehireupdates.xml contains the information for cycle availability at each station
1. I need to create a table with two columns. One for 'Station Name' and the other for 'No of cycles available'
2. I need to write code that only takes in the above link as input and extracts values of 'Name' and 'nbEmptyDocks'.
Ex : <name> ABC,Surrey </name> <nbEmptyDocks> 10 </nbEmptyDocks>, how will I extract the values ABC,Surrey and 10 and place them in respective columns?
<!DOCTYPE html>
<html>
<body>
<script language= "JavaScript">
document.write('<br> <br><table width="50%" border="1">'); document.write('<th> Dock Station');
document.write('<th> Number of Cycles');
document.write('<br> <br><table width="50%" border="1">');
var Connect = new XMLHttpRequest();
Connect.open("GET", "http://www.tfl.gov.uk/tfl/syndication/feeds/cycle-hire/livecyclehireupdates.xml", false);
Connect.setRequestHeader("Content-Type", "text/xml");
Connect.send(null);
var TheDocument = Connect.responseXML;
var station = TheDocument.childNodes[0];
for (var i = 0; i < 5; i++)
{
var stations = station.children[i];
var name = stations.getElementsByTagName("name");
var avail = Customer.getElementsByTagName("nbEmptyDocks");
document.write("<tr><td>");
document.write( name[0].textContent.toString());
document.write("</td><td>");
document.write(avail[0].textContent.toString());
document.write("</td>");
document.write("</tr>");
}
document.write (" </table>");
</script>
</body></html>
On further reading, I understood that the above code might not work for Chrome, and I need one that works with chrome.
<html>
<body>
<script>
var xmlDoc;
var xmlloaded = false;
function initLibrary()
{
importXML("http:///www.somedomain.com/somesubdir/somefile.xml");
}
function importXML(xmlfile)
{
try
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", xmlfile, false);
}
catch (Exception)
{
var ie = (typeof window.ActiveXObject != 'undefined');
if (ie)
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
while(xmlDoc.readyState != 4) {};
xmlDoc.load(xmlfile);
readXML();
xmlloaded = true;
}
else
{
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.onload = readXML;
xmlDoc.load(xmlfile);
xmlloaded = true;
}
}
if (!xmlloaded)
{
xmlhttp.setRequestHeader('Content-Type', 'text/xml')
xmlhttp.send("");
xmlDoc = xmlhttp.responseXML;
readXML();
xmlloaded = true;
}
}
</script>
</body>
</html>
But this doesnt seem to work either
I would suggest using Google API for grabbing RSS and rending it on your page: you can get started here.
As you say they are not tags themselves, for which it would've been fairly trivial to access them via DOM methods.
Instead, you will need to grab the textContent of the <title> and/or <description> nodes in each <item>. Once you have done that, you will need to do a little string processing. However, the strings are quite predictable, so this is easy:
var text = "Max Temp: 8°C (46°F), Min Temp: 5°C (41°F), Wind Direction: SW, Wind Speed: 8mph, Visibility: good, Pressure: 1002mb, Humidity: 92%, Pollution: n/a, Sunrise: 08:13GMT, Sunset: 16:40GMT";
var pairs = text.split(", "),
info = {};
for (var i=0; i<pairs.length; i++) {
var pair = pairs[i].split(": ");
info[pair[0]] = pair[1];
}
console.log(info)
// {"Max Temp":"8°C (46°F)","Min Temp":"5°C (41°F)","Wind Direction":"SW","Wind Speed":"8mph","Visibility":"good","Pressure":"1002mb","Humidity":"92%","Pollution":"n/a","Sunrise":"08:13GMT","Sunset":"16:40GMT"}
console.log(info["Max Temp"], info["Min Temp"])
// "8°C (46°F)", "5°C (41°F)"

Google Map javascript MarkerManager markers not showing

I have a map that reads an XML file; it's all very simple and copied from here:
http://geochalkboard.wordpress.com/2009/03/30/reading-xml-files-with-the-google-maps-api/
My version is here:
http://www.cloudfund.me/maps/mashup.html and the data file it's reading is here:
converted.xml in the same directory.
I don't get any points at all, when I run it. I put some console logging in to see if I could see anything, but as far as that's concerned, it just runs through without a hitch. The file loads ok, and I can watch the code loop through all the rows (208 in this example) without any problems.
The only warning I'm getting is the 'Resource interpreted as other passed as undefined' one; having had a look at some of the other threads, I can't see anything that helps - no empty src links, etc. As far as I can tell, this shouldn't stop it marking the points, either.
Here's the real kicker - in trying to trace this error, I set up an exact replica of the original code on my own server, and got an error about null fields, which I added some conditional code to to sort; this version works on my server. This is austin.html in the same directory (sorry, can't do more than two links in my first posts!)
So - my code is this:
<title>Test </title>
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=AIzaSyDgybFoyn3i5j_6d7ul7p2dPNQ5b1xOWnk"
type="text/javascript">console.log("Loaded Maps API");</script>
<script src="http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/src/markermanager.js">console.log("MarkerManager");</script>
<script type="text/javascript">
console.log("Into Main Script");
function initialize() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(51.39906378, -2.449545605), 13);
map.setUIToDefault();
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addMapType(G_PHYSICAL_MAP);
map.setMapType(G_PHYSICAL_MAP);
console.log("Reached end of map initialising");
addMarkersFromXML();
console.log("MarkersfromXML")
}
}
function addMarkersFromXML(){
var batch = [];
mgr = new MarkerManager(map);
var request = GXmlHttp.create();
console.log("About to open converted.xml")
request.open('GET', 'converted.xml', true);
console.log("Opened Converted.xml")
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200)
{
var xmlDoc = request.responseXML;
var xmlrows = xmlDoc.documentElement.getElementsByTagName("row");
for (var i = 0; i < xmlrows.length; i++) {
var xmlrow = xmlrows[i];
console.log("Running through row number",i)
var xmlcellLongitude = xmlrow.getElementsByTagName("longitude")[0];
console.log(xmlcellLongitude);
var xmlcellLatitude = xmlrow.getElementsByTagName("latitude")[0];
var point = new GLatLng(parseFloat(xmlcellLatitude.firstChild.data),parseFloat(xmlcellLongitude.firstChild.data));
//get the PAO
var xmlcellAssetName = xmlrow.getElementsByTagName("pao")[0];
console.log(xmlcellAssetName);
var celltextAssetName = xmlcellAssetName.firstChild.data;
//get the area
var xmlcellArea = xmlrow.getElementsByTagName("area")[0];
console.log(xmlcellArea);
var celltextArea = xmlcellArea.firstChild.data;
//get the land type
var xmlcellLandType = xmlrow.getElementsByTagName("landtype")[0];
console.log(xmlcellLandType);
var celltextLandType = xmlcellLandType.firstChild.data;
//get the Planning Permissions
var xmlcellPlanning = xmlrow.getElementsByTagName("planning")[0];
console.log(xmlcellPlanning);
var celltextPlanning = xmlcellPlanning.firstChild.data;
var htmlString = "Asset Name: " + celltextAssetName + "<br>" + "Size: " + celltextArea + "<br>" + "Land Type: " + celltextLandType + "<br>" + "Planning Permissions: " + celltextPlanning;
//var htmlString = 'yes'
var marker = createMarker(point,htmlString);
batch.push(marker);
}
mgr.addMarkers(batch,50);
mgr.refresh();
}
}
request.send(null);
}
function createMarker(point,html) {
var marker = new GMarker(point);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(html);
});
return marker;
}
</script>
</head>
<body onload="initialize()" onunload="GUnload()">
<div id="map_canvas" style="width: 1100px; height: 700px"></div>
</body>
</html>
Think you have a typo. In your code, you're pulling an incomplete URL for the API:
<script src="//maps.google.com/maps?file=api&v=2&sensor=false&key=AIzaSyDgybFoyn3i5j_6d7ul7p2dPNQ5b1xOWnk"
That errant // seems to be throwing the code off.
Though, to be perfectly honest, the originating example (and austin.html) doesn't exactly work as one would imagine it should. The points do get rendered, but no effective clustering takes place when you zoom out. Suspect that the 2.0 branch of the API got moved to a newer version and created a bit of an incompatibility.
Recommend that you rewrite this in API version 3. There is a cluster manager that works for it quite well.
See http://tools.voanews2.com/nuclear_reactors/

Categories

Resources