简体   繁体   中英

Empty list in SAX parser endDocument after successfully parsing elements to the list

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.

Try this way,hope this will help you to solve your problem.

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;
            List<ArrayList<MapPos>> ways = new ArrayList<ArrayList<MapPos>>();

            @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 = new ArrayList<MapPos>();
                    nodeBuffer.add(nodes.get(ref));
                }
            }

            @Override
            public void endElement(String uri, String localName,String qName) throws SAXException {
                if (qName.equalsIgnoreCase("way")) {
                    ways.add(nodeBuffer);
                }
            }

            @Override
            public void endDocument() throws SAXException {
                roads = ways;
            }
        };

        saxParser.parse("file://" + Environment.getExternalStorageDirectory() + "/roadmap.xml", handler);
        return roads;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM