package se.slide.sgu; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import se.slide.sgu.model.Episode; import se.slide.sgu.model.Item; import se.slide.sgu.model.Link; import se.slide.sgu.model.Quote; import se.slide.sgu.model.Section; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class SectionParser { // We don't use namespaces private static final String ns = null; public List<Episode> parse(InputStream in) throws XmlPullParserException, IOException { try { XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(in, null); parser.nextTag(); return readXml(parser); } finally { in.close(); } } private List<Episode> readXml(XmlPullParser parser) throws XmlPullParserException, IOException { List<Episode> listOfEpisodes = new ArrayList<Episode>(); parser.require(XmlPullParser.START_TAG, ns, "sgu"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("episode")) { listOfEpisodes.add(readEpisode(parser)); } else { skip(parser); } } return listOfEpisodes; } // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off // to their respective "read" methods for processing. Otherwise, skips the tag. private Episode readEpisode(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "episode"); Episode episode = new Episode(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); /* if (name.equals("mp3")) { episode.mp3 = getText(parser, "mp3"); } */ if (name.equals("guid")) { episode.guid = getText(parser, "guid"); } else if (name.equals("title")) { episode.title = getText(parser, "title"); } else if (name.equals("transcript")) { episode.transcript = getText(parser, "transcript"); } else if (name.equals("description")) { episode.description = getText(parser, "description"); } else if (name.equals("image")) { episode.image = getText(parser, "image"); } else if (name.equals("sections")) { episode.listOfSection = readSections(parser); } else if (name.equals("hosts")) { episode.hosts = readHosts(parser); } else if (name.equals("quote")) { episode.quote = readQuote(parser); } else if (name.equals("scienceorfiction")) { episode.listOfItem = readScienceorfiction(parser); } else { skip(parser); } } // Set the unique guid for each section for (Section section : episode.listOfSection) { section.guid = episode.guid; for (Link link : section.listOfLinks) { link.guid = episode.guid; } } for (Item item : episode.listOfItem) { item.guid = episode.guid; for (Link link : item.listOfLinks) { link.guid = episode.guid; } } if (episode.quote != null) episode.quote.guid = episode.guid; return episode; } private List<Item> readScienceorfiction(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "scienceorfiction"); List<Item> listOfItem = new ArrayList<Item>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("item")) { listOfItem.add(readItem(parser)); } else { skip(parser); } } return listOfItem; } private Item readItem(XmlPullParser parser) throws XmlPullParserException, IOException, NumberFormatException { parser.require(XmlPullParser.START_TAG, ns, "item"); Item item = new Item(); List<Link> listOfLinks = new ArrayList<Link>(); boolean science = true; //default to science? ;) String sci = parser.getAttributeValue(null, "science"); if (sci != null && sci.equalsIgnoreCase("false")) science = false; item.science = science; while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("title")) { item.title = getText(parser, "title"); } else if (name.equals("description")) { item.description = getText(parser, "description"); } else if (name.equals("link")) { item.link = getText(parser, "link"); Link link = new Link(); link.url = item.link; listOfLinks.add(link); } else { skip(parser); } } for (Link link : listOfLinks) { link.belongsToSection = Link.BELONG_TO_SCIENCE_OR_FICTION; link.title = item.title; } item.listOfLinks = listOfLinks; return item; } private Quote readQuote(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "quote"); Quote quote = new Quote(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("text")) { quote.text = getText(parser, "text"); } else if (name.equals("by")) { quote.by = getText(parser, "by"); } else { skip(parser); } } return quote; } private String readHosts(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "hosts"); List<String> hosts = new ArrayList<String>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("host")) { hosts.add(readHost(parser)); } else { skip(parser); } } // Convert to SQLite friendly String StringBuilder builder = new StringBuilder(); for (int i = 0; i < hosts.size(); i++) { String id = hosts.get(i); if (id == null) continue; builder.append(hosts.get(i)); if (i < hosts.size() - 1) builder.append(";"); } return builder.toString(); } private String readHost(XmlPullParser parser) throws XmlPullParserException, IOException, NumberFormatException { parser.require(XmlPullParser.START_TAG, ns, "host"); String id = parser.getAttributeValue(null, "id"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } skip(parser); } return id; } // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off // to their respective "read" methods for processing. Otherwise, skips the tag. private List<Section> readSections(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "sections"); List<Section> sections = new ArrayList<Section>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("section")) { sections.add(readSection(parser)); } else { skip(parser); } } return sections; } private Section readSection(XmlPullParser parser) throws XmlPullParserException, IOException, NumberFormatException { parser.require(XmlPullParser.START_TAG, ns, "section"); String number = null; String title = null; String start = null; List<Link> listOfLinks = new ArrayList<Link>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("number")) { number = getText(parser, "number"); } else if (name.equals("title")) { title = getText(parser, "title"); } else if (name.equals("link")) { String url = getText(parser, "link"); Link link = new Link(); link.url = url; listOfLinks.add(link); } else if (name.equals("start")) { start = getText(parser, "start"); } else { skip(parser); } } // These might go wrong int num = Integer.valueOf(number); int sta = Formatter.convertStartToSeconds(start); for (Link link : listOfLinks) { link.belongsToSection = Link.BELONG_TO_SECTION; link.number = num; link.title = title; } Section section = new Section(); section.title = title; section.number = num; section.start = sta; section.listOfLinks = listOfLinks; return section; } private String getText(XmlPullParser parser, String tag) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, ns, tag); String text = readText(parser); parser.require(XmlPullParser.END_TAG, ns, tag); return text; } // For the tags title and summary, extracts their text values. private String readText(XmlPullParser parser) throws IOException, XmlPullParserException { String result = ""; if (parser.next() == XmlPullParser.TEXT) { result = parser.getText(); 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; } } } }