/******************************************************************************* * Copyright 2012 Crazywater * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package de.knufficast.logic; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.xmlpull.v1.XmlPullParserException; import de.knufficast.logic.db.DBFeed; import de.knufficast.logic.xml.XMLEpisode; import de.knufficast.logic.xml.XMLFeed; /** * A parser for XML podcast feeds. Produces {@link DBFeed} objects. * * @author crazywater * */ public class RssParser extends XmlParser { private List<XMLFeed> feeds; private String feedUrl; private long timestamp; private String eTag; private XMLFeed feed; private XMLEpisode episode; private static final String FEED_TAG = "channel"; private static final String ENCLOSURE_TAG = "enclosure"; private static final String DESCRIPTION_TAG = "description"; private static final String TITLE_TAG = "title"; private static final String GUID_TAG = "guid"; private static final String EPISODE_TAG = "item"; private static final String LINK_TAG = "link"; private static final String IMAGE_TAG = "image"; private static final String CONTENT_TAG = "encoded"; private static final String LOCATION_ATTRIBUTE = "href"; private static final String URL_ATTRIBUTE = "url"; private static final String REL_ATTRIBUTE = "rel"; public void parse(InputStream xml, String feedUrl, long timestamp, String eTag) throws XmlPullParserException, IOException { feeds = new ArrayList<XMLFeed>(); this.feedUrl = feedUrl; this.timestamp = timestamp; this.eTag = eTag; this.parseFrom(xml); } /** * Returns the parsed feeds from a previous call to {@link #parseFrom} or null * if no call was made. */ public List<XMLFeed> getFeeds() { return feeds; } /** * Called upon parsing an opening tag. * * @param tag * the tag name * @param attributes * the attributes of the tag (name->value) mapping */ protected void openTag(String tag, Map<String, String> attributes) { if (tag.equals(FEED_TAG)) { feed = new XMLFeed(); feed.setDataUrl(feedUrl); feed.setLastUpdated(timestamp); feed.setETag(eTag); feed.setEncoding(getEncoding()); } else if (tag.equals(EPISODE_TAG)) { episode = new XMLEpisode(); } else if (tag.equals(IMAGE_TAG)) { String location = attributes.get(LOCATION_ATTRIBUTE); if (location != null) { if (FEED_TAG.equals(getParentTag())) { feed.setImgUrl(location); } else if (EPISODE_TAG.equals(getParentTag())) { episode.setImgUrl(location); } } } else if (tag.equals(ENCLOSURE_TAG) && EPISODE_TAG.equals(getParentTag())) { episode.setDataUrl(attributes.get(URL_ATTRIBUTE)); } else if (tag.equals(LINK_TAG) && EPISODE_TAG.equals(getParentTag())) { if ("payment".equals(attributes.get(REL_ATTRIBUTE))) { String paymentLocation = attributes.get(LOCATION_ATTRIBUTE); if (paymentLocation != null && paymentLocation.contains("flattr")) { episode.setFlattrUrl(paymentLocation); } } } } /** * Called upon parsing a closing tag * * @param tag * the tag name */ protected void closeTag(String tag) { if (tag.equals(FEED_TAG)) { feeds.add(feed); feed = null; } if (tag.equals(EPISODE_TAG)) { feed.addEpisode(episode); episode = null; } } /** * Called upon parsing text between an opening and a closing tag. Parent tags * can be found in {@link #currentTags}, but include the current tag at the * top. * * @param text * the text that is encountered */ protected void tagText(String text) { String tag = getCurrentTag(); if (tag.equals(TITLE_TAG) && EPISODE_TAG.equals(getParentTag())) { episode.setTitle(text); } else if (tag.equals(GUID_TAG) && EPISODE_TAG.equals(getParentTag())) { episode.setGuid(text); } else if (tag.equals(CONTENT_TAG) && EPISODE_TAG.equals(getParentTag())) { episode.setContent(text); } else if (tag.equals(TITLE_TAG) && FEED_TAG.equals(getParentTag())) { feed.setTitle(text); } else if (tag.equals(DESCRIPTION_TAG) && EPISODE_TAG.equals(getParentTag())) { episode.setDescription(text); } else if (tag.equals(DESCRIPTION_TAG) && FEED_TAG.equals(getParentTag())) { feed.setDescription(text); } } }