I'm trying to parse an XML containing geographic nodes and ways connecting the nodes using SAX parser. I store the parsed nodes in an ArrayMap<Long, MapPos>
and the ways in an ArrayList<ArrayList<MapPos>>
. When parsing a way, I create an ArrayList<MapPos>
of the referenced nodes and add this to the ArrayList
of ways.
After debugging the application, I see that startElement()
and endElement()
successfully adds the ways to the ArrayList
, but in the endDocument()
method the ways ArrayList
contains nothing but a bunch of empty ArrayList
.
Here is the java class:
public class ParkingDataExtractor {
private static List<ArrayList<MapPos>> roads = new ArrayList<ArrayList<MapPos>>();
public static List<ArrayList<MapPos>> getWaysFromXML()
throws ParserConfigurationException, SAXException, IOException{
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
DefaultHandler handler = new DefaultHandler() {
ArrayMap<Long, MapPos> nodes = new ArrayMap<Long, MapPos>();
ArrayList<MapPos> nodeBuffer = new ArrayList<MapPos>();
List<ArrayList<MapPos>> ways = new ArrayList<ArrayList<MapPos>>();
// private int i; // for debug purposes
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("node")) {
Long id = Long.parseLong(attributes.getValue("id"));
Float lat = Float
.parseFloat(attributes.getValue("lat"));
Float lon = Float
.parseFloat(attributes.getValue("lon"));
nodes.put(id, new MapPos(lat, lon));
} else if (qName.equalsIgnoreCase("nd")) {
Long ref = Long.parseLong(attributes.getValue("ref"));
nodeBuffer.add(nodes.get(ref));
}
}
@Override
public void endElement(String uri, String localName,
String qName) throws SAXException {
if (qName.equalsIgnoreCase("way")) {
ways.add(nodeBuffer);
// i++;
// if(i==1590) // last element
// ArrayList<MapPos> test = ways.get(i-1); // test = [MapPos [x=..., y=..., z=0.0], MapPos [x=..., y=..., z=0.0],...]
nodeBuffer.clear();
}
}
@Override
public void endDocument() throws SAXException {
// ArrayList<MapPos> test = ways.get(i-1); // test = []
roads = ways;
}
};
saxParser.parse("file://" + Environment.getExternalStorageDirectory()
+ "/roadmap.xml", handler);
return roads;
}
}
When you call nodeBuffer.clear()
you empty the list that you have just passed on to ways. You basically use the same nodeBuffer
object over and over, and fill the ways
list with a lot of references to the same object - which you empty each time.
The way you should do it is create a new ArrayList
object using new
and assign it to nodeBuffer
every time. You will then have separate objects, each containing the list of nodes parsed in the latest round.