/* * Taken from the 'Learning Android' project, * released as Public Domain software at * http://github.com/digitalspaghetti/learning-android * and modified heavily for Transdroid */ package org.ifies.android.sax; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.transdroid.util.HttpHelper; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.io.IOException; import java.util.Date; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class RssParser extends DefaultHandler { public RssParser(String url) { this.urlString = url; this.text = new StringBuilder(); } /** * Returns the feed as a RssFeed, which is a ListArray * @return RssFeed rssFeed */ public Channel getChannel() { return (this.channel); } public void parse() throws ParserConfigurationException, SAXException, IOException { HttpClient httpclient = initialise(); HttpResponse result = httpclient.execute(new HttpGet(urlString)); //FileInputStream urlInputStream = new FileInputStream("/sdcard/rsstest2.txt"); SAXParserFactory spf = SAXParserFactory.newInstance(); if (spf != null) { SAXParser sp = spf.newSAXParser(); sp.parse(result.getEntity().getContent(), this); } } /** * Instantiates an HTTP client that can be used for all requests. */ protected HttpClient initialise() { return HttpHelper.buildDefaultSearchHttpClient(false); } /** * By default creates a standard Item (with title, description and links), which may to overriden to add more data. * @return A possibly decorated Item instance */ protected Item createNewItem() { return new Item(); } public void startElement(String uri, String localName, String qName, Attributes attributes) { /** First lets check for the channel */ if (localName.equalsIgnoreCase("channel")) { this.channel = new Channel(); } /** Now lets check for an item */ if (localName.equalsIgnoreCase("item") && (this.channel != null)) { this.item = createNewItem(); this.channel.addItem(this.item); } /** Now lets check for an image */ if (localName.equalsIgnoreCase("image") && (this.channel != null)) { this.imgStatus = true; } /** Checking for a enclosure */ if (localName.equalsIgnoreCase("enclosure")) { /** Lets check we are in an item */ if (this.item != null && attributes != null && attributes.getLength() > 0) { if (attributes.getValue("url") != null) { this.item.setEnclosureUrl(parseLink(attributes.getValue("url"))); } if (attributes.getValue("type") != null) { this.item.setEnclosureType(attributes.getValue("type")); } if (attributes.getValue("length") != null) { this.item.setEnclosureLength(Long.parseLong(attributes.getValue("length"))); } } } } /** * This is where we actually parse for the elements contents */ public void endElement(String uri, String localName, String qName) { /** Check we have an RSS Feed */ if (this.channel == null) { return; } /** Check are at the end of an item */ if (localName.equalsIgnoreCase("item")) { this.item = null; } /** Check we are at the end of an image */ if (localName.equalsIgnoreCase("image")) { this.imgStatus = false; } /** Now we need to parse which title we are in */ if (localName.equalsIgnoreCase("title")) { /** We are an item, so we set the item title */ if (this.item != null) { this.item.setTitle(this.text.toString().trim()); /** We are in an image */ } else { this.channel.setTitle(this.text.toString().trim()); } } /** Now we are checking for a link */ if (localName.equalsIgnoreCase("link")) { /** Check we are in an item **/ if (this.item != null) { this.item.setLink(parseLink(this.text.toString())); /** Check we are in an image */ } else if (this.imgStatus) { this.channel.setImage(parseLink(this.text.toString())); /** Check we are in a channel */ } else { this.channel.setLink(parseLink(this.text.toString())); } } /** Checking for a description */ if (localName.equalsIgnoreCase("description")) { /** Lets check we are in an item */ if (this.item != null) { this.item.setDescription(this.text.toString().trim()); /** Lets check we are in the channel */ } else { this.channel.setDescription(this.text.toString().trim()); } } /** Checking for a pubdate */ if (localName.equalsIgnoreCase("pubDate")) { /** Lets check we are in an item */ if (this.item != null) { try { this.item.setPubdate(new Date(Date.parse(this.text.toString().trim()))); } catch (Exception e) { // Date is malformed (not parsable by Date.parse) } /** Lets check we are in the channel */ } else { try { this.channel.setPubDate(new Date(Date.parse(this.text.toString().trim()))); } catch (Exception e) { // Date is malformed (not parsable by Date.parse) } } } /** Check for the category */ if (localName.equalsIgnoreCase("category") && (this.item != null)) { this.channel.addCategory(this.text.toString().trim()); } addAdditionalData(localName, this.item, this.text.toString()); this.text.setLength(0); } /** * May be overridden to add additional data from tags that are not standard in RSS. Not used by this default RSS style parser. * @param localName The tag name * @param item The Item we are currently parsing * @param text The new text content */ protected void addAdditionalData(String localName, Item item, String text) { } public void characters(char[] ch, int start, int length) { this.text.append(ch, start, length); } private String parseLink(String string) { return string.trim(); } private String urlString; private Channel channel; private StringBuilder text; private Item item; private boolean imgStatus; }