I'm trying to plot circles using d3 from an xml file (xml osm generated by the overpass api). I'm getting an error TypeError: null is not an object (evaluating 'node.getAttribute')
. I've been able to plot geometry with geojson & csv data, but am simply struggling with the xml. What am I missing?
Of course I am aiming to have the 4 nodes in the xml file displayed.
HTML:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<script type="text/javascript" src="https://d3js.org/d3.v4.js"></script>
</head>
<body>
<script>
var svg = d3.select("svg"),
width = svg.attr("width"),
height = svg.attr("height");
var projection = d3.geoMercator()
.scale(21000000)
.center([-122.29576905, 37.890256])
.translate([width / 3, height / 4])
d3.xml("entrance-exit.xml", function ready(error, xml) {
svg
.selectAll("myCircles")
.data(xml.documentElement.getElementsByTagName("node"))
.enter()
.append("myCircles")
.attr("cx", function(d) { return d.getAttribute("lon"); })
.attr("cy", function(d) { return d.getAttribute("lat"); })
.attr("r", 8)
.style("fill", "blue")
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill-opacity", 1);
})
</script>
</body>
</html>
XML:
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API 0.7.59 e21c39fe">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base="2022-11-01T11:22:37Z"/>
<bounds minlat="37.8885000" minlon="-122.2966000" maxlat="37.8906000" maxlon="-122.2945000"/>
<node id="10054221950" lat="37.8899635" lon="-122.2960219">
<tag k="entrance" v="yes"/>
</node>
<node id="10054221951" lat="37.8894885" lon="-122.2951210">
<tag k="entrance" v="yes"/>
<tag k="wheelchair" v="yes"/>
</node>
<node id="10091017732" lat="37.8894072" lon="-122.2952833">
<tag k="entrance" v="yes"/>
<tag k="ref" v="25"/>
</node>
<node id="10091017733" lat="37.8894276" lon="-122.2951869">
<tag k="entrance" v="yes"/>
<tag k="ref" v="26"/>
</node>
</osm>
CodePudding user response:
I didn't get your error when trying to reproduce your case using your code but I found several mistakes that should be fixed in order to display the points.
First I replaced the myCircles
tag by a simple SVG circle
element and then I set the cx and cy attributes by using the result of the projection (which you haven't used apparently):
svg
.selectAll("circle")
.data(xml.documentElement.getElementsByTagName("node"))
.enter()
.append("circle")
.each(function (d) {
const projected = projection([
d.getAttribute("lon"),
d.getAttribute("lat"),
]);
d3.select(this).attr("cx", projected[0]).attr("cy", projected[1]);
})
...
Then depending on your SVG element size, the points may be out of bound so adjust the scale accordingly to see them.