package com.lemoulinstudio.bikefriend.parser; import android.util.Xml; import com.lemoulinstudio.bikefriend.Utils; import com.lemoulinstudio.bikefriend.db.BikeStation; import com.lemoulinstudio.bikefriend.db.DataSourceEnum; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; /** * This parser extracts information from a data source in XML. * * @author Vincent Cantin */ public class CityBikeStationXmlParserV1 implements BikeStationParser { // No namespace. private final String ns = null; private DataSourceEnum dataSource; public void setDataSource(DataSourceEnum dataSource) { this.dataSource = dataSource; } @Override public List<BikeStation> parse(InputStream in) throws IOException, ParsingException { try { XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(in, null); // Move to the interesting part. while (parser.getEventType() != XmlPullParser.START_TAG || !parser.getName().equals("BIKEStation")) { parser.next(); } return readStations(parser); } catch (XmlPullParserException e) { throw new ParsingException(e); } finally { in.close(); } } private List<BikeStation> readStations(XmlPullParser parser) throws XmlPullParserException, IOException { List<BikeStation> stations = new ArrayList<BikeStation>(); parser.require(XmlPullParser.START_TAG, ns, "BIKEStation"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() == XmlPullParser.START_TAG) { if (parser.getName().equals("Station")) { BikeStation station = readStation(parser); if (station.isValid()) { stations.add(station); } } else { skip(parser); } } } return stations; } private BikeStation readStation(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "Station"); BikeStation station = new BikeStation(); station.dataSource = dataSource; station.lastUpdate = new Date(); while (parser.nextTag() != XmlPullParser.END_TAG) { String tagName = parser.getName(); if (tagName.equals("StationID")) { station.id = dataSource.idPrefix + safeNextText(parser); parser.require(XmlPullParser.END_TAG, ns, "StationID"); } else if (tagName.equals("StationName")) { station.chineseName = safeNextText(parser); parser.require(XmlPullParser.END_TAG, ns, "StationName"); } else if (tagName.equals("StationAddress")) { station.chineseAddress = safeNextText(parser); parser.require(XmlPullParser.END_TAG, ns, "StationAddress"); } else if (tagName.equals("StationDescription")) { station.chineseDescription = safeNextText(parser); parser.require(XmlPullParser.END_TAG, ns, "StationDescription"); } else if (tagName.equals("StationLon")) { // Note: In the xml, latitude and longitude are mixed up. station.latitude = Utils.parseFloat(safeNextText(parser), 0.0f); parser.require(XmlPullParser.END_TAG, ns, "StationLon"); } else if (tagName.equals("StationLat")) { // Note: In the xml, latitude and longitude are mixed up. station.longitude = Utils.parseFloat(safeNextText(parser), 0.0f); parser.require(XmlPullParser.END_TAG, ns, "StationLat"); } else if (tagName.equals("StationNums1")) { station.nbBicycles = Utils.parseInt(safeNextText(parser), -1); parser.require(XmlPullParser.END_TAG, ns, "StationNums1"); } else if (tagName.equals("StationNums2")) { station.nbEmptySlots = Utils.parseInt(safeNextText(parser), -1); parser.require(XmlPullParser.END_TAG, ns, "StationNums2"); } else { skip(parser); } } parser.require(XmlPullParser.END_TAG, ns, "Station"); return station; } private String safeNextText(XmlPullParser parser) throws XmlPullParserException, IOException { String result = parser.nextText(); if (parser.getEventType() != XmlPullParser.END_TAG) { parser.nextTag(); } return result; } private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { if (parser.getEventType() != XmlPullParser.START_TAG) { throw new IllegalStateException(); } int depth = 1; while (depth != 0) { switch (parser.next()) { case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth++; break; } } } }